后缀数组
poj 1743
poj 3415
poj 2758
线段树
poj 2828
每个人依次插队, pos表示这个人会差到第pos个人的右边, 树状数组维护,开始的时候全置1,表示每个位置都有一个人,就是最终的状态,然后按照时间顺序 倒序处理. 先处理最后一个人, 二分出前n项和等于其pos+1的位置, 那么这个人就会在这个位置, 对于最后一个人, 他恰好在 pos位置, 然后最后一个人的位置确定了, 树状数组改位置清零, 状态就是除去这个人的状态, 然后处理倒数第二个人, 以此类推. 线段树有个比较巧妙的写法,3年前的工作了, 也贴一下吧. 虽然测试没快多少, 但是树状数组n*logn*logn,因为有二分, 线段树只有nlogn. 线段树结点存区间的和, 查询一个值时, 左儿子和如果足够,就走左边, 否则减去左边的和,剩余部分走右边,返回走到叶子结点的id.
array
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 //#define txtout 2 //#define debug 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<stack> 13 #include<queue> 14 #include<set> 15 #include<map> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double pi=acos(-1.0); 20 const double eps=1e-8; 21 const int inf=0x3f3f3f3f; 22 const int M=2e5+10; 23 class One_Tree_Array { ///一维树状数组 24 static const int M=2e5+10; ///点的个数 25 typedef int typev; 26 typev a[M]; 27 int n; 28 public: 29 void init(int tn) { ///传入点数,点下标 1 开始 30 n=tn; 31 for(int i=0; i<=n; i++) a[i]=0; 32 } 33 int lowb(int t) { 34 return t&(-t); 35 } 36 void add(int i,typev v) { 37 for(; i<=n; a[i]+=v,i+=lowb(i)); 38 } 39 typev sum(int i) { 40 typev s=0; 41 for(; i>0; s+=a[i],i-=lowb(i)); 42 return s; 43 } 44 } tree; 45 int n; 46 struct Q { 47 int pos,val; 48 } p[M]; 49 int answer[M]; 50 int Binary(int x){ 51 int L=0,R=n-1,result=0; 52 while(L<=R){ 53 int mid=(L+R)>>1; 54 if(tree.sum(mid+1)>=x){ 55 result=mid; 56 R=mid-1; 57 } 58 else{ 59 L=mid+1; 60 } 61 } 62 return result; 63 } 64 void solve() { 65 tree.init(n); 66 for(int i=1;i<=n;i++){ 67 tree.add(i,1); 68 } 69 for(int i=n-1;i>=0;i--){ 70 int to=Binary(p[i].pos+1); 71 answer[to]=p[i].val; 72 tree.add(to+1,-1); 73 } 74 } 75 int main() { 76 #ifdef txtout 77 freopen("in.txt","r",stdin); 78 freopen("out.txt","w",stdout); 79 #endif // txtout 80 while(~scanf("%d",&n)) { 81 for(int i=0; i<n; i++) { 82 scanf("%d%d",&p[i].pos,&p[i].val); 83 } 84 solve(); 85 for(int i=0; i<n; i++) { 86 if(i) putchar(' '); 87 printf("%d",answer[i]); 88 } 89 puts(""); 90 } 91 return 0; 92 }
segment tree
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<cstdio> 2 const int M=200010; 3 int tree[M<<2]; 4 int ans[M]; 5 int pos[M]; 6 int val[M]; 7 void build(int L,int R,int rt){ 8 tree[rt]=R-L+1; 9 if(L!=R){ 10 int mid=(L+R)>>1; 11 build(L,mid,rt<<1); 12 build(mid+1,R,rt<<1|1); 13 } 14 } 15 int update(int x,int L,int R,int rt){ 16 tree[rt]--; 17 if(L==R){ 18 return L; 19 } 20 int mid=(L+R)>>1; 21 if(tree[rt<<1]>=x){ 22 return update(x,L,mid,rt<<1); 23 } 24 else{ 25 x-=tree[rt<<1]; 26 return update(x,mid+1,R,rt<<1|1); 27 } 28 } 29 int main(){ 30 int n; 31 while(~scanf("%d",&n)){ 32 build(1,n,1); 33 for(int i=1;i<=n;i++){ 34 scanf("%d%d",&pos[i],&val[i]); 35 } 36 for(int i=n;i>=1;i--){ 37 int k=update(pos[i]+1,1,n,1); 38 ans[k]=val[i]; 39 } 40 for(int i=1;i<=n;i++){ 41 printf("%d ",ans[i]); 42 } 43 puts(""); 44 } 45 return 0; 46 }
poj 3468
区间+值,区间求和,线段树区间更新基础。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<stack> 13 #include<queue> 14 #include<set> 15 #include<map> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e5+10; 23 class SegmentTree{ 24 #define lrrt int L,int R,int rt 25 #define iall 1,n,1 26 #define imid int mid=(L+R)>>1 27 #define lson L,mid,rt<<1 28 #define rson mid+1,R,rt<<1|1 29 static const int MV=1e5+10; 30 struct T{ 31 LL sum,lazy; 32 }tree[MV<<2]; 33 int n; 34 void build(lrrt,int a[]){ 35 tree[rt].lazy=0; 36 if(L==R){ 37 tree[rt].sum=a[L]; 38 return ; 39 } 40 imid; 41 build(lson,a); 42 build(rson,a); 43 pushup(rt); 44 } 45 void pushup(int rt){ 46 tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; 47 } 48 void pushdown(int mid,lrrt){ 49 if(tree[rt].lazy){ 50 tree[rt<<1].sum+=tree[rt].lazy*(mid-L+1); 51 tree[rt<<1|1].sum+=tree[rt].lazy*(R-mid); 52 tree[rt<<1].lazy+=tree[rt].lazy; 53 tree[rt<<1|1].lazy+=tree[rt].lazy; 54 tree[rt].lazy=0; 55 } 56 } 57 void update(int x,int y,LL z,lrrt){ 58 if(x<=L&&R<=y){ 59 tree[rt].sum+=(R-L+1)*z; 60 tree[rt].lazy+=z; 61 return ; 62 } 63 imid; 64 pushdown(mid,L,R,rt); 65 if(mid>=x) update(x,y,z,lson); 66 if(mid<y) update(x,y,z,rson); 67 pushup(rt); 68 } 69 LL querySum(int x,int y,lrrt){ 70 if(x<=L&&R<=y) return tree[rt].sum; 71 imid; 72 pushdown(mid,L,R,rt); 73 LL sum=0; 74 if(mid>=x) sum+=querySum(x,y,lson); 75 if(mid<y) sum+=querySum(x,y,rson); 76 return sum; 77 } 78 public: 79 void init(int tn,int a[]){ 80 n=tn; 81 build(iall,a); 82 } 83 void update(int x,int y,LL z){ 84 update(x,y,z,iall); 85 } 86 LL querySum(int x,int y){ 87 return querySum(x,y,iall); 88 } 89 }st; 90 int n,m; 91 int a[M]; 92 vector<LL> answer; 93 struct Q{ 94 int x,y,z; 95 char type[4]; 96 }q[M]; 97 void solve(){ 98 st.init(n,a); 99 answer.clear(); 100 for(int i=0;i<m;i++){ 101 if(q[i].type[0]=='Q'){ 102 answer.push_back(st.querySum(q[i].x,q[i].y)); 103 continue; 104 } 105 st.update(q[i].x,q[i].y,q[i].z); 106 } 107 } 108 int main() { 109 #ifdef txtout 110 freopen("in.txt","r",stdin); 111 freopen("out.txt","w",stdout); 112 #endif // txtout 113 while(~scanf("%d%d",&n,&m)) { 114 for(int i=1; i<=n; i++) { 115 scanf("%d",&a[i]); 116 } 117 for(int i=0;i<m;i++){ 118 scanf("%s%d%d",q[i].type,&q[i].x,&q[i].y); 119 if(q[i].type[0]=='C'){ 120 scanf("%d",&q[i].z); 121 } 122 } 123 solve(); 124 for(int i=0; i<answer.size(); i++) { 125 printf("%I64d\n",answer[i]); 126 } 127 } 128 return 0; 129 }
poj 2528
区间赋值,查询有多少个不同的值。坐标较大需要离散化。线段树区间赋值,单点查询基础。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<stack> 13 #include<queue> 14 #include<set> 15 #include<map> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e4+10; 23 class SegmentTree{ 24 #define lrrt int L,int R,int rt 25 #define iall 1,n,1 26 #define imid int mid=(L+R)>>1 27 #define lson L,mid,rt<<1 28 #define rson mid+1,R,rt<<1|1 29 static const int MV=1e5+10; 30 struct T{ 31 int sum,cover; 32 }tree[MV<<2]; 33 int n; 34 void build(lrrt){ 35 tree[rt].sum=0; 36 tree[rt].cover=0; 37 if(L==R) return ; 38 imid; 39 build(lson); 40 build(rson); 41 } 42 void pushdown(int mid,lrrt){ 43 if(tree[rt].cover){ 44 tree[rt<<1].cover=tree[rt].cover; 45 tree[rt<<1|1].cover=tree[rt].cover; 46 tree[rt<<1].sum=tree[rt].cover*(mid-L+1); 47 tree[rt<<1|1].sum=tree[rt].cover*(R-mid); 48 tree[rt].cover=0; 49 } 50 } 51 void change(int x,int y,int z,lrrt){ 52 if(x<=L&&R<=y){ 53 tree[rt].sum=(R-L+1)*z; 54 tree[rt].cover=z; 55 return ; 56 } 57 imid; 58 pushdown(mid,L,R,rt); 59 if(mid>=x) change(x,y,z,lson); 60 if(mid<y) change(x,y,z,rson); 61 } 62 int querySum(int x,int y,lrrt){ 63 if(x<=L&&R<=y) return tree[rt].sum; 64 imid; 65 pushdown(mid,L,R,rt); 66 int sum=0; 67 if(mid>=x) sum+=querySum(x,y,lson); 68 if(mid<y) sum+=querySum(x,y,rson); 69 return sum; 70 } 71 public: 72 void init(int tn){ 73 n=tn; 74 build(iall); 75 } 76 void change(int x,int y,int z){ 77 change(x,y,z,iall); 78 } 79 int querySum(int x,int y){ 80 return querySum(x,y,iall); 81 } 82 }st; 83 int n; 84 struct A{ 85 int x,y; 86 }a[M]; 87 map<int,int> mp; 88 vector<int> buffer; 89 void init_map(){ 90 buffer.clear(); 91 for(int i=0;i<n;i++){ 92 buffer.push_back(a[i].x); 93 buffer.push_back(a[i].y); 94 } 95 sort(buffer.begin(),buffer.end()); 96 mp.clear(); 97 int id=1; 98 for(int i=0;i<buffer.size();i++){ 99 if(mp.count(buffer[i])) continue; 100 mp[buffer[i]]=id++; 101 } 102 } 103 int solve(){ 104 init_map(); 105 int total=mp.size(); 106 st.init(total); 107 for(int i=0;i<n;i++){ 108 st.change(mp[a[i].x],mp[a[i].y],i+1); 109 } 110 buffer.clear(); 111 for(int i=1;i<=total;i++){ 112 buffer.push_back(st.querySum(i,i)); 113 } 114 sort(buffer.begin(),buffer.end()); 115 buffer.push_back(-1); 116 int answer=0; 117 for(int i=0;i+1<buffer.size();i++){ 118 if(buffer[i]!=buffer[i+1]){ 119 answer++; 120 } 121 } 122 return answer; 123 } 124 int main(){ 125 #ifdef txtout 126 freopen("in.txt","r",stdin); 127 freopen("out.txt","w",stdout); 128 #endif // txtout 129 int t; 130 while(~scanf("%d",&t)){ 131 while(t--){ 132 scanf("%d",&n); 133 for(int i=0;i<n;i++){ 134 scanf("%d%d",&a[i].x,&a[i].y); 135 } 136 printf("%d\n",solve()); 137 } 138 } 139 return 0; 140 }
上面代码虽能ac,但实际上有错,不知道poj样例水了? 15 ,12,45,这一组答案应是3, 上面代码返回2, 原因是离散化有问题. 下面给13年的代码, 离散化的时候注意两个点不相邻的时候, 离散化后也应该不相邻,增加一个中间值就行.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int M=10000010; 5 int myset[M]; 6 int mymap[M]; 7 bool v[M]; 8 int lazy[M<<2]; 9 struct G{ 10 int x,y; 11 }g[10010]; 12 void build(int L,int R,int rt){ 13 lazy[rt]=0; 14 if(L==R){ 15 return ; 16 } 17 int mid=(L+R)>>1; 18 build(L,mid,rt<<1); 19 build(mid+1,R,rt<<1|1); 20 } 21 void pushdown(int rt){ 22 if(lazy[rt]){ 23 if(lazy[rt<<1]<lazy[rt]) 24 lazy[rt<<1]=lazy[rt]; 25 if(lazy[rt<<1|1]<lazy[rt]) 26 lazy[rt<<1|1]=lazy[rt]; 27 lazy[rt]=0; 28 } 29 } 30 void update(int x,int y,int val,int L,int R,int rt){ 31 if(x<=L&&R<=y){ 32 if(lazy[rt]<val) 33 lazy[rt]=val; 34 } 35 else{ 36 int mid=(L+R)>>1; 37 pushdown(rt); 38 if(mid>=x) 39 update(x,y,val,L,mid,rt<<1); 40 if(mid<y) 41 update(x,y,val,mid+1,R,rt<<1|1); 42 } 43 } 44 void get(int L,int R,int rt){ 45 if(L==R){ 46 v[lazy[rt]]=true; 47 } 48 else{ 49 int mid=(L+R)>>1; 50 pushdown(rt); 51 get(L,mid,rt<<1); 52 get(mid+1,R,rt<<1|1); 53 } 54 } 55 int main(){ 56 int t,n,m; 57 while(~scanf("%d",&t)){ 58 while(t--){ 59 scanf("%d",&m); 60 int ls=0; 61 for(int i=0;i<m;i++){ 62 scanf("%d%d",&g[i].x,&g[i].y); 63 myset[ls++]=g[i].x; 64 myset[ls++]=g[i].y; 65 } 66 sort(myset,myset+ls); 67 int id=0; 68 myset[ls]=0; 69 for(int i=0;i<ls;i++){ 70 if(myset[i]!=myset[i+1]){ 71 myset[id++]=myset[i]; 72 } 73 } 74 ls=id; 75 myset[ls]=0; 76 n=1; 77 for(int i=0;i<ls;i++,n++){ 78 mymap[myset[i]]=n; 79 if(myset[i+1]!=myset[i]+1){ 80 n++; 81 } 82 } 83 build(1,n,1); 84 int val=1; 85 for(int i=0;i<m;i++,val++){ 86 update(mymap[g[i].x],mymap[g[i].y],val,1,n,1); 87 } 88 for(int i=1;i<=val;i++){ 89 v[i]=false; 90 } 91 get(1,n,1); 92 int ans=0; 93 for(int i=1;i<=val;i++){ 94 if(v[i]){ 95 ans++; 96 } 97 } 98 printf("%d\n",ans); 99 } 100 } 101 return 0; 102 }
poj 3667
酒店有n个房间,开始都空, 每次来个团, 她们要求要连续的k个房间,不存在输出0, 存在就把起点最靠左边的输出,并占用这一段房间. 线段树, 一开始全1 ,表示每个房间都可用, 更新就是区间赋值1或0.
线段树4个值,big是该区间最大连续子段的长度, left是区间左端点为起点的最长连续子段长度, right是右端点为终点, cover是区间赋值的延迟标记. 一个区间最长可能有3种情况 ,完全在左儿子, 完全在右儿子, 左儿子的right + 右儿子的left.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 //#define txtout 2 //#define debug 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<stack> 13 #include<queue> 14 #include<set> 15 #include<map> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double pi=acos(-1.0); 20 const double eps=1e-8; 21 const int inf=0x3f3f3f3f; 22 const int M=5e4+10; 23 class SegmentTree{ 24 #define lrrt int L,int R,int rt 25 #define iall 1,n,1 26 #define imid int mid=(L+R)>>1 27 #define lson L,mid,rt<<1 28 #define rson mid+1,R,rt<<1|1 29 static const int MV=5e4+10; 30 struct T{ 31 int big,left,right,cover; 32 }tree[MV<<2]; 33 int n; 34 void pushup(int mid,lrrt){ 35 tree[rt].big=max(tree[rt<<1].big,tree[rt<<1|1].big); 36 tree[rt].big=max(tree[rt].big,tree[rt<<1].right+tree[rt<<1|1].left); 37 tree[rt].left=tree[rt<<1].left; 38 if(tree[rt].left==mid-L+1){ 39 tree[rt].left+=tree[rt<<1|1].left; 40 } 41 tree[rt].right=tree[rt<<1|1].right; 42 if(tree[rt].right==R-mid){ 43 tree[rt].right+=tree[rt<<1].right; 44 } 45 } 46 void build(lrrt){ 47 tree[rt].cover=-1; 48 if(L==R){ 49 tree[rt].big=1; 50 tree[rt].left=1; 51 tree[rt].right=1; 52 return ; 53 } 54 imid; 55 build(lson); 56 build(rson); 57 pushup(mid,L,R,rt); 58 } 59 void pushdown(int mid,lrrt){ 60 if(tree[rt].cover!=-1){ 61 tree[rt<<1].cover=tree[rt].cover; 62 tree[rt<<1|1].cover=tree[rt].cover; 63 int lvalue=(mid-L+1)*tree[rt].cover; 64 tree[rt<<1].big=lvalue; 65 tree[rt<<1].left=lvalue; 66 tree[rt<<1].right=lvalue; 67 int rvalue=(R-mid)*tree[rt].cover; 68 tree[rt<<1|1].big=rvalue; 69 tree[rt<<1|1].left=rvalue; 70 tree[rt<<1|1].right=rvalue; 71 tree[rt].cover=-1; 72 } 73 } 74 void update(int x,int y,int z,lrrt){ 75 if(x<=L&&R<=y){ 76 tree[rt].cover=z; 77 int value=(R-L+1)*z; 78 tree[rt].big=value; 79 tree[rt].left=value; 80 tree[rt].right=value; 81 return ; 82 } 83 imid; 84 pushdown(mid,L,R,rt); 85 if(mid>=x) update(x,y,z,lson); 86 if(mid<y) update(x,y,z,rson); 87 pushup(mid,L,R,rt); 88 } 89 int query(int x,lrrt){ 90 if(L==R) return L; 91 imid; 92 pushdown(mid,L,R,rt); 93 if(tree[rt<<1].big>=x) return query(x,lson); 94 if(tree[rt<<1].right+tree[rt<<1|1].left>=x) return mid-tree[rt<<1].right+1; 95 return query(x,rson); 96 } 97 public: 98 void init(int tn){ 99 n=tn; 100 build(iall); 101 } 102 int query(int len){ 103 if(tree[1].big<len) return 0; 104 return query(len,iall); 105 } 106 void update(int x,int y,int z){ 107 update(x,y,z,iall); 108 } 109 }st; 110 int n,m; 111 struct Q{ 112 int type,x,y; 113 }q[M]; 114 vector<int> answer; 115 void solve(){ 116 st.init(n); 117 answer.clear(); 118 for(int i=0;i<m;i++){ 119 if(q[i].type==1){ 120 int result=st.query(q[i].x); 121 answer.push_back(result); 122 if(result){ 123 st.update(result,result+q[i].x-1,0); 124 } 125 continue; 126 } 127 st.update(q[i].x,q[i].x+q[i].y-1,1); 128 } 129 } 130 int main() { 131 #ifdef txtout 132 freopen("in.txt","r",stdin); 133 freopen("out.txt","w",stdout); 134 #endif // txtout 135 while(~scanf("%d%d",&n,&m)) { 136 for(int i=0; i<m; i++) { 137 scanf("%d%d",&q[i].type,&q[i].x); 138 if(q[i].type==2){ 139 scanf("%d",&q[i].y); 140 } 141 } 142 solve(); 143 for(int i=0; i<answer.size(); i++) { 144 printf("%d\n",answer[i]); 145 } 146 } 147 return 0; 148 }
处理特殊图
poj 1041 uva302
poj 2337 zoj 1919
uva 216
uva 10944
poj 1776 zoj 2359 uva 2954
poj 1419 uva 193
poj 1144 zoj 1311 uva 315
poj 3352
相关题库
poj 2774
poj 3261
poj 2777
一开始n个点都是颜色1, 操作会把某一个区间的颜色都变成 z, 查询某个区间有多少种不同颜色. 现在的写法, 因为颜色只有30位, 一开始开了30个线段树分别存某种颜色, 对于某个颜色的某个位置, 要么是, 要么不是, 超时了, 用二进制每一位表示每个颜色, 1表示有, 0表示没有这个颜色, 合并就是或操作了. 查询就是查1的个数了.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 //#define txtout 2 //#define debug 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<stack> 13 #include<queue> 14 #include<set> 15 #include<map> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double pi=acos(-1.0); 20 const double eps=1e-8; 21 const int inf=0x3f3f3f3f; 22 const int M=1e5+10; 23 class SegmentTree{ 24 #define lrrt int L,int R,int rt 25 #define iall 1,n,1 26 #define imid int mid=(L+R)>>1 27 #define lson L,mid,rt<<1 28 #define rson mid+1,R,rt<<1|1 29 static const int MV=1e5+10; 30 struct T{ 31 int value; 32 int cover; 33 }tree[MV<<2]; 34 int n; 35 void pushup(int rt){ 36 tree[rt].value=tree[rt<<1].value|tree[rt<<1|1].value; 37 } 38 void build(lrrt){ 39 tree[rt].cover=-1; 40 tree[rt].value=1; 41 if(L==R) return ; 42 imid; 43 build(lson); 44 build(rson); 45 } 46 void pushdown(int rt){ 47 if(tree[rt].cover!=-1){ 48 tree[rt<<1].cover=tree[rt].cover; 49 tree[rt<<1|1].cover=tree[rt].cover; 50 tree[rt<<1].value=tree[rt].cover; 51 tree[rt<<1|1].value=tree[rt].cover; 52 tree[rt].cover=-1; 53 } 54 } 55 void update(int x,int y,int z,lrrt){ 56 if(x<=L&&R<=y){ 57 tree[rt].cover=1<<(z-1); 58 tree[rt].value=1<<(z-1); 59 return ; 60 } 61 imid; 62 pushdown(rt); 63 if(mid>=x) update(x,y,z,lson); 64 if(mid<y) update(x,y,z,rson); 65 pushup(rt); 66 } 67 int query(int x,int y,lrrt){ 68 if(x<=L&&R<=y) return tree[rt].value; 69 imid; 70 pushdown(rt); 71 int result=0; 72 if(mid>=x) result|=query(x,y,lson); 73 if(mid<y) result|=query(x,y,rson); 74 return result; 75 } 76 public: 77 void init(int tn){ 78 n=tn; 79 build(iall); 80 } 81 int query(int x,int y){ 82 return query(x,y,iall); 83 } 84 void update(int x,int y,int z){ 85 update(x,y,z,iall); 86 } 87 }st; 88 int n,t,m; 89 struct Q{ 90 int x,y,z; 91 char type[4]; 92 }q[M]; 93 vector<int> answer; 94 void solve(){ 95 st.init(n); 96 answer.clear(); 97 for(int i=0;i<m;i++){ 98 if(q[i].x>q[i].y) swap(q[i].x,q[i].y); 99 if(q[i].type[0]=='C'){ 100 st.update(q[i].x,q[i].y,q[i].z); 101 continue; 102 } 103 int sum=0; 104 int result=st.query(q[i].x,q[i].y); 105 for(int j=0;j<t;j++){ 106 if((result>>j)&1) sum++; 107 } 108 answer.push_back(sum); 109 } 110 } 111 int main() { 112 #ifdef txtout 113 freopen("in.txt","r",stdin); 114 freopen("out.txt","w",stdout); 115 #endif // txtout 116 while(~scanf("%d%d%d",&n,&t,&m)) { 117 for(int i=0; i<m; i++) { 118 scanf("%s%d%d",q[i].type,&q[i].x,&q[i].y); 119 if(q[i].type[0]=='C'){ 120 scanf("%d",&q[i].z); 121 } 122 } 123 solve(); 124 for(int i=0; i<answer.size(); i++) { 125 printf("%d\n",answer[i]); 126 } 127 } 128 return 0; 129 }
13年写的, 是如果一个区间都是一个颜色, 就是这个颜色, 否则为0, 查询时 遇到一个区间是同一种颜色的 ,直接返回, 否则暴力搜 . 颜色比较少, 可能样例水吧 这么做也能过, 复杂度不好估计.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<cstdio> 2 #define lson L,mid,rt<<1 3 #define rson mid+1,R,rt<<1|1 4 const int M=100010; 5 int tree[M<<2],lazy[M<<2]; 6 bool v[64]; 7 void pushup(int rt){ 8 if(tree[rt<<1]==tree[rt<<1|1]){ 9 tree[rt]=tree[rt<<1]; 10 } 11 else{ 12 tree[rt]=0; 13 } 14 } 15 void build(int L,int R,int rt){ 16 lazy[rt]=0; 17 tree[rt]=1; 18 if(L==R){ 19 return ; 20 } 21 int mid=(L+R)>>1; 22 build(lson); 23 build(rson); 24 } 25 void pushdown(int rt){ 26 if(lazy[rt]){ 27 lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; 28 tree[rt]=tree[rt<<1]=tree[rt<<1|1]=lazy[rt]; 29 lazy[rt]=0; 30 } 31 } 32 void update(int x,int y,int z,int L,int R,int rt){ 33 if(x<=L&&R<=y){ 34 lazy[rt]=z; 35 tree[rt]=z; 36 return ; 37 } 38 int mid=(L+R)>>1; 39 pushdown(rt); 40 if(mid>=x) 41 update(x,y,z,lson); 42 if(mid<y) 43 update(x,y,z,rson); 44 pushup(rt); 45 } 46 void query(int x,int y,int L,int R,int rt){ 47 if(x<=L&&R<=y){ 48 if(tree[rt]){ 49 v[tree[rt]]=true; 50 return ; 51 } 52 } 53 int mid=(L+R)>>1; 54 pushdown(rt); 55 if(mid>=x) 56 query(x,y,lson); 57 if(mid<y) 58 query(x,y,rson); 59 } 60 int main(){ 61 int n,t,m; 62 while(~scanf("%d%d%d",&n,&t,&m)){ 63 build(1,n,1); 64 while(m--){ 65 int a,b,c; 66 char s[4]; 67 scanf("%s%d%d",s,&a,&b); 68 if(a>b){ 69 int temp=a; 70 a=b; 71 b=temp; 72 } 73 if(s[0]=='C'){ 74 scanf("%d",&c); 75 update(a,b,c,1,n,1); 76 } 77 else{ 78 for(int i=1;i<=t;i++){ 79 v[i]=false; 80 } 81 int ans=0; 82 query(a,b,1,n,1); 83 for(int i=1;i<=t;i++){ 84 if(v[i]){ 85 ans++; 86 } 87 } 88 printf("%d\n",ans); 89 } 90 } 91 } 92 return 0; 93 }
poj 2886
poj 3225
poj 1436,zoj 1391, uva 2441
poj 2991
poj 1308, zoj 1268 ,uva 615
uva 117
uva 10735
uva 10054 uva 2036
uva 10818
uva 10937