标签:express 区间更新 first sam 必须 was define end 区间
Input
Output
Sample Input
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2
Sample Output21
思路:填色,一开始完全没思路,看了下其他大佬的思路,因为颜色数量只有30可以用二进制来表示颜色,含有1代表有这种颜色,如101,代表有第一三种颜色,共两种。子区间可以通过‘|‘符号(或 的意思)来合并出上一级区间的状态如 101 | 110 = 111 .父区间含有三种颜色。因为查询操作较多,必须用线段树区间更新,主要是延迟标记,而且要用scanf输入.
实现代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<cmath> using namespace std; const int M = 1e6+10; int n,w,e; int color[M<<2],lazy[M<<2]; void pushup(int rt){ color[rt] = color[rt*2]|color[rt*2+1]; } void build(int l,int r,int rt){ if(l==r){ color[rt] = 1; return ; } int m = (l+r)/2; build(l,m,rt*2); build(m+1,r,rt*2+1); pushup(rt); } void pushdown(int rt){ if(lazy[rt]){ lazy[rt*2] = (1<<(lazy[rt]-1)); lazy[rt*2+1] = (1<<(lazy[rt]-1)); color[rt*2] = color[rt]; color[rt*2+1] = color[rt]; lazy[rt] = 0; } } void update(int L,int R,int l,int r,int x,int rt){ if(L<=l&&r<=R){ lazy[rt] = x; color[rt] = (1<<(x-1)); return ; } pushdown(rt); int m = (l+r)/2; if(L<=m) update(L,R,l,m,x,rt*2); if(R>m) update(L,R,m+1,r,x,rt*2+1); pushup(rt); } int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return color[rt]; } int ans1=0,ans2=0,ans; int m = (l+r)/2; pushdown(rt); if(L<=m) ans1+=query(L,R,l,m,rt*2); if(R>m) ans2+=query(L,R,m+1,r,rt*2+1); ans = ans1|ans2; return ans; } void getsum(int x){ int ans = 0; while(x){ if(x%2==1) ans++; x/=2; } cout<<ans<<endl; } int main() { int L,R,x; char c; while(scanf("%d%d%d",&n,&w,&e)!=EOF){ memset(lazy,0,sizeof(lazy)); build(1,n,1); while(e--){ scanf("%c",&c); while(c==‘ ‘||c == ‘\n‘) scanf("%c",&c); if(c==‘C‘){ scanf("%d%d%d",&L,&R,&x); if(L>R) swap(L,R); update(L,R,1,n,x,1); } else{ scanf("%d%d",&L,&R); if(L>R) swap(L,R); int cnt = query(L,R,1,n,1); getsum(cnt); } } } return 0; }
标签:express 区间更新 first sam 必须 was define end 区间
原文地址:http://www.cnblogs.com/kls123/p/7528341.html