后缀数组
poj 1743
poj 3415
poj 2758
线段树
poj 2828
每个人依次插队, pos表示这个人会差到第pos个人的右边, 树状数组维护,开始的时候全置1,表示每个位置都有一个人,就是最终的状态,然后按照时间顺序 倒序处理. 先处理最后一个人, 二分出前n项和等于其pos+1的位置, 那么这个人就会在这个位置, 对于最后一个人, 他恰好在 pos位置, 然后最后一个人的位置确定了, 树状数组改位置清零, 状态就是除去这个人的状态, 然后处理倒数第二个人, 以此类推. 线段树有个比较巧妙的写法,3年前的工作了, 也贴一下吧. 虽然测试没快多少, 但是树状数组n*logn*logn,因为有二分, 线段树只有nlogn. 线段树结点存区间的和, 查询一个值时, 左儿子和如果足够,就走左边, 否则减去左边的和,剩余部分走右边,返回走到叶子结点的id.
array
1 //#define txtout
2 //#define debug
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include<set>
15 #include
View Code
segment tree
1 #include
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 }
View Code
poj 3468
区间+值,区间求和,线段树区间更新基础。
1 //#define debug
2 //#define txtout
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include<set>
15 #include
View Code
poj 2528
区间赋值,查询有多少个不同的值。坐标较大需要离散化。线段树区间赋值,单点查询基础。
1 //#define debug
2 //#define txtout
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include<set>
15 #include
View Code
上面代码虽能ac,但实际上有错,不知道poj样例水了? 15 ,12,45,这一组答案应是3, 上面代码返回2, 原因是离散化有问题. 下面给13年的代码, 离散化的时候注意两个点不相邻的时候, 离散化后也应该不相邻,增加一个中间值就行.
1 #include
2 #include
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){
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){
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){
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){
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 }
View Code
poj 3667
酒店有n个房间,开始都空, 每次来个团, 她们要求要连续的k个房间,不存在输出0, 存在就把起点最靠左边的输出,并占用这一段房间. 线段树, 一开始全1 ,表示每个房间都可用, 更新就是区间赋值1或0.
线段树4个值,big是该区间最大连续子段的长度, left是区间左端点为起点的最长连续子段长度, right是右端点为终点, cover是区间赋值的延迟标记. 一个区间最长可能有3种情况 ,完全在左儿子, 完全在右儿子, 左儿子的right + 右儿子的left.
1 //#define txtout
2 //#define debug
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include<set>
15 #include
View Code
处理特殊图
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的个数了.
1 //#define txtout
2 //#define debug
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include<set>
15 #include
View Code
13年写的, 是如果一个区间都是一个颜色, 就是这个颜色, 否则为0, 查询时 遇到一个区间是同一种颜色的 ,直接返回, 否则暴力搜 . 颜色比较少, 可能样例水吧 这么做也能过, 复杂度不好估计.
1 #include
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 }
View Code
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