2013 UESTC ACM Training for Data Structure

 

又到了一年招新的时候,数据结构又是第一个专题,简要写一下本专题的解题报告

先附上本专题题目地址:2013 UESTC ACM Training for Data Structure 不是本校的同学可以先看看题目

由于题目较多,不再一一叙述题意,只是简要的说说做法再贴个代码

 

A题 Hotel

 

简单线段树,可能实现起来比较困难,不过做法是比较容易想到的

 

参考代码

 

A
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 
 7 struct Interval_Tree
 8 {
 9     static const int N=50006;
10     struct node
11     {
12         int s, t, Lmax, Rmax, Max, tag;
13     } T[N<<2];
14 
15     inline void Fill(int id, int tag)
16     {
17         T[id].Lmax=T[id].Rmax=T[id].Max=(T[id].t-T[id].s+1)*tag;
18     }
19 
20     inline void pushUp(int id)
21     {
22         T[id].Lmax=T[id<<1].Lmax;
23         if(T[id<<1].t-T[id<<1].s+1==T[id<<1].Lmax) T[id].Lmax+=T[id<<1|1].Lmax;
24         T[id].Rmax=T[id<<1|1].Rmax;
25         if(T[id<<1|1].t-T[id<<1|1].s+1==T[id<<1|1].Rmax) T[id].Rmax+=T[id<<1].Rmax;
26         T[id].Max=max(max(T[id<<1].Max, T[id<<1|1].Max), T[id<<1].Rmax+T[id<<1|1].Lmax);
27     }
28 
29     inline void pushDown(int id)
30     {
31         T[id<<1].tag=T[id<<1|1].tag=T[id].tag;
32         Fill(id<<1, T[id].tag), Fill(id<<1|1, T[id].tag);
33         T[id].tag=-1;
34     }
35 
36     void build(int id, int L, int R)
37     {
38         T[id].s=L, T[id].t=R, T[id].tag=-1;
39         Fill(id, 1);
40         if(L==R) return;
41         int mid=(L+R)>>1;
42         build(id<<1, L, mid), build(id<<1|1, mid+1, R);
43     }
44 
45     int query(int id, int len)
46     {
47         if(T[id].Max<len) return 0;
48         if(T[id].s==T[id].t) return T[id].s;
49         if(T[id].Lmax>=len) return T[id].s;
50         if(T[id].tag!=-1) pushDown(id);
51         if(T[id<<1].Max>=len) return query(id<<1, len);
52         else if(T[id<<1].Rmax+T[id<<1|1].Lmax>=len) return T[id<<1].t-T[id<<1].Rmax+1;
53         else return query(id<<1|1, len);
54     }
55 
56     void update(int id, int L, int R, int tag)
57     {
58         if(L<=T[id].s && T[id].t<=R)
59         {
60             Fill(id, T[id].tag=tag);
61             return;
62         }
63         int mid=(T[id].s+T[id].t)>>1;
64         if(T[id].tag!=-1) pushDown(id);
65         if(R<=mid) update(id<<1, L, R, tag);
66         else if(L>mid) update(id<<1|1, L, R, tag);
67         else update(id<<1, L, R, tag), update(id<<1|1, L, R, tag);
68         pushUp(id);
69     }
70 } tree;
71 
72 int main()
73 {
74     int n, m;
75     scanf("%d%d", &n, &m);
76     tree.build(1, 1, n);
77     for(int i=0, a, b ,c; i<m; i++)
78     {
79         scanf("%d", &a);
80         if(a==1)
81         {
82             scanf("%d", &b);
83             int c=tree.query(1, b);
84             printf("%d\n", c);
85             if(c!=0) tree.update(1, c, c+b-1, 0);
86         }
87         else
88         {
89             scanf("%d%d", &b, &c);
90             tree.update(1, b, b+c-1, 1);
91         }
92     }
93     return 0;
94 }

 

B题 Little Girl and Problem on Trees

 

一道CF原题,还是可以用线段树做,由于题目所给的树的特殊性,可以把树上的链条拆开,单独处理树的根节点,这样就变成最基本的简单线段树了,这道题过的人最少

 

参考代码

 

B
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <vector>
  5 
  6 using namespace std;
  7 
  8 const int N=100006;
  9 typedef long long LL;
 10 
 11 struct Interval_Tree
 12 {
 13     struct node
 14     {
 15         int s, t;
 16         LL val, lazy;
 17         void init(int a, int b)
 18         {
 19             s=a, t=b, val=0ll, lazy=0ll;
 20         }
 21     } T[N<<2];
 22 
 23     void build(int id, int L, int R)
 24     {
 25         T[id].init(L, R);
 26         if(L==R) return;
 27         int mid=(L+R)>>1;
 28         build(id<<1, L, mid), build(id<<1|1, mid+1, R);
 29     }
 30 
 31     inline void pushDown(int id)
 32     {
 33         T[id<<1].lazy+=T[id].lazy;
 34         T[id<<1|1].lazy+=T[id].lazy;
 35         T[id<<1].val+=(T[id<<1].t-T[id<<1].s+1)*T[id].lazy;
 36         T[id<<1|1].val+=(T[id<<1|1].t-T[id<<1|1].s+1)*T[id].lazy;
 37         T[id].lazy=0ll;
 38     }
 39 
 40     void update(int id, int L, int R, LL val)
 41     {
 42         if(L<=T[id].s && T[id].t<=R)
 43         {
 44             T[id].lazy+=val;
 45             T[id].val+=(T[id].t-T[id].s+1)*val;
 46             return;
 47         }
 48         int mid=(T[id].s+T[id].t)>>1;
 49         if(T[id].lazy!=0) pushDown(id);
 50         if(R<=mid) update(id<<1, L, R, val);
 51         else if(L>mid) update(id<<1|1, L, R, val);
 52         else update(id<<1, L, R, val), update(id<<1|1, L, R, val);
 53         T[id].val=T[id<<1].val+T[id<<1|1].val;
 54     }
 55 
 56     LL query(int id, int pos)
 57     {
 58         if(T[id].s==T[id].t) return T[id].val;
 59         int mid=(T[id].s+T[id].t)>>1;
 60         if(T[id].lazy!=0) pushDown(id);
 61         if(pos<=mid) return query(id<<1, pos);
 62         else return query(id<<1|1, pos);
 63     }
 64 } tree;
 65 
 66 int s[N], t[N], label[N], de[N], belong[N];
 67 int n, q, root, cnt;
 68 vector <int> arc[N];
 69 
 70 void DFS(int u, int pre, int cur)
 71 {
 72     label[u]=++cnt, belong[u]=cur;
 73     int len=(int)arc[u].size();
 74     bool flag=true;
 75     for(int i=0; i<len; i++)
 76     {
 77         int v=arc[u][i];
 78         if(v==pre) continue;
 79         flag=false;
 80         DFS(v, u, cur);
 81     }
 82     if(flag) t[cur]=label[u];
 83 }
 84 
 85 int main()
 86 {
 87     while(scanf("%d%d", &n, &q)!=EOF)
 88     {
 89         for(int i=1; i<=n; i++)
 90             arc[i].clear(), de[i]=0, t[i]=-1;
 91         root=-1;
 92         for(int i=1, a, b; i<n; i++)
 93         {
 94             scanf("%d%d", &a, &b);
 95             arc[a].push_back(b);
 96             arc[b].push_back(a);
 97             de[a]++, de[b]++;
 98             if(root==-1 && de[a]==1) root=a;
 99             if(root==-1 && de[b]==1) root=b;
100             if((root==-1 || de[root]==1) && de[a]>2) root=a;
101             if((root==-1 || de[root]==1) && de[b]>2) root=b;
102         }
103         cnt=0;
104         int len=(int)arc[root].size();
105         for(int i=0; i<len; i++)
106         {
107             s[i+1]=cnt+1;
108             DFS(arc[root][i], root, i+1);
109         }
110         label[root]=++cnt;
111         tree.build(1, 1, cnt);
112         for(int i=0, flag, v, x, d; i<q; i++)
113         {
114             scanf("%d", &flag);
115             if(flag==0)
116             {
117                 scanf("%d%d%d", &v, &x, &d);
118                 if(v==root)
119                 {
120                     tree.update(1, label[root], label[root], x);
121                     if(x<=0) continue;
122                     for(int j=1; j<=len; j++)
123                         tree.update(1, s[j], min(t[j], s[j]+d-1), x);
124                 }
125                 else
126                 {
127                     tree.update(1, label[v], min(label[v]+d, t[belong[v]]), x);
128                     tree.update(1, max(s[belong[v]], label[v]-d), label[v], x);
129                     tree.update(1, label[v], label[v], -x);
130                     if(d<=label[v]-s[belong[v]]) continue;
131                     tree.update(1, label[root], label[root], x);
132                     d-=label[v]-s[belong[v]]+1;
133                     if(d==0) continue;
134                     for(int j=1; j<=len; j++)
135                     {
136                         if(j==belong[v]) continue;
137                         tree.update(1, s[j], min(s[j]+d-1, t[j]), x);
138                     }
139                 }
140                 continue;
141             }
142             scanf("%d", &v);
143             printf("%lld\n", tree.query(1, label[v]));
144         }
145     }
146     return 0;
147 }

 

C题 Sliding Window

 

经典双端队列题目,做法不再累述

 

参考代码

 

C
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 const int N=1000006;
 8 
 9 int Q[N], data[N], Min[N], Max[N];
10 int n, k, head, tail;
11 
12 void deal_min()
13 {
14     head=tail=0;
15     for(int i=0; i<k; i++)
16     {
17         while(head!=tail && data[Q[tail-1]]>=data[i]) tail--;
18         Q[tail++]=i;
19     }
20     Min[0]=data[Q[head]];
21     for(int i=k; i<n; i++)
22     {
23         while(head!=tail && data[Q[tail-1]]>=data[i]) tail--;
24         Q[tail++]=i;
25         while(head!=tail && Q[head]<i-k+1) head++;
26         Min[i-k+1]=data[Q[head]];
27     }
28 }
29 
30 void deal_max()
31 {
32     head=tail=0;
33     for(int i=0; i<k; i++)
34     {
35         while(head!=tail && data[Q[tail-1]]<=data[i]) tail--;
36         Q[tail++]=i;
37     }
38     Max[0]=data[Q[head]];
39     for(int i=k; i<n; i++)
40     {
41         while(head!=tail && data[Q[tail-1]]<=data[i]) tail--;
42         Q[tail++]=i;
43         while(head!=tail && Q[head]<i-k+1) head++;
44         Max[i-k+1]=data[Q[head]];
45     }
46 }
47 int main()
48 {
49     scanf("%d%d", &n, &k);
50     for(int i=0; i<n; i++) scanf("%d", data+i);
51     deal_min();
52     deal_max();
53     for(int i=0; i<=n-k; i++)
54     {
55         printf("%d", Min[i]);
56         if(i==n-k) printf("\n");
57         else printf(" ");
58     }
59     for(int i=0; i<=n-k; i++)
60     {
61         printf("%d", Max[i]);
62         if(i==n-k) printf("\n");
63         else printf(" ");
64     }
65     return 0;
66 }

 

D题 Picture

 

扫描线求矩形周长并

我贴的别人的模板

 

参考代码

 

D
  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <algorithm>
  5 #define N 10003
  6 #define lson l,m,k<<1
  7 #define rson m,r,k<<1|1
  8 using namespace std;
  9 struct segment
 10 {
 11     int len,cover;
 12 };
 13 struct line1
 14 {
 15     int x,y1,y2;
 16     int flag;
 17     bool operator<(const line1 &L) const
 18     {
 19         if(x==L.x) return flag>L.flag;
 20         return x<L.x;
 21     }
 22 };
 23 struct line2
 24 {
 25     int y,x1,x2;
 26     int flag;
 27     bool operator<(const line2 &L) const
 28     {
 29         if(y==L.y) return flag>L.flag;
 30         return y<L.y;
 31     }
 32 };
 33 segment st[N<<2];
 34 line1 L1[N];
 35 line2 L2[N];
 36 int rcx[N],rcy[N];
 37 void up1(int &k,int &l,int &r)
 38 {
 39     if(st[k].cover)
 40         st[k].len=rcy[r]-rcy[l];
 41     else if(l+1==r)
 42         st[k].len=0;
 43     else
 44         st[k].len=st[k<<1].len+st[k<<1|1].len;
 45 }
 46 void up2(int &k,int &l,int &r)
 47 {
 48     if(st[k].cover)
 49         st[k].len=rcx[r]-rcx[l];
 50     else if(l+1==r)
 51         st[k].len=0;
 52     else
 53         st[k].len=st[k<<1].len+st[k<<1|1].len;
 54 }
 55 void build(int l,int r,int k)
 56 {
 57     st[k].cover=st[k].len=0;
 58     if(l+1==r)
 59         return ;
 60     int m=(l+r)>>1;
 61     build(lson);
 62     build(rson);
 63 }
 64 int flag;
 65 void update1(int &y1,int &y2,int l,int r,int k)
 66 {
 67     if(y1<=rcy[l]&&rcy[r]<=y2)
 68     {
 69         st[k].cover+=flag;
 70         up1(k,l,r);
 71         return ;
 72     }
 73     int m=(l+r)>>1;
 74     if(y1<rcy[m]) update1(y1,y2,lson);
 75     if(y2>rcy[m]) update1(y1,y2,rson);
 76     up1(k,l,r);
 77 }
 78 void update2(int &x1,int &x2,int l,int r,int k)
 79 {
 80     if(x1<=rcx[l]&&rcx[r]<=x2)
 81     {
 82         st[k].cover+=flag;
 83         up2(k,l,r);
 84         return ;
 85     }
 86     int m=(l+r)>>1;
 87     if(x1<rcx[m]) update2(x1,x2,lson);
 88     if(x2>rcx[m]) update2(x1,x2,rson);
 89     up2(k,l,r);
 90 }
 91 int main()
 92 {
 93     int n,nl,pl,len;
 94     int i,j,k;
 95     int x1,x2,y1,y2;
 96     while(scanf("%d",&n)!=EOF)
 97     {
 98         for(j=i=0; i<n; i++)
 99         {
100             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
101             L1[j].x=x1;
102             L1[j].y1=y1;
103             L1[j].y2=y2;
104             L2[j].y=y1;
105             L2[j].x1=x1;
106             L2[j].x2=x2;
107             L1[j].flag=L2[j].flag=1;
108             rcx[j]=x1;
109             rcy[j]=y1;
110             j++;
111 
112             rcx[j]=x2;
113             rcy[j]=y2;
114             L1[j].x=x2;
115             L1[j].y1=y1;
116             L1[j].y2=y2;
117             L2[j].y=y2;
118             L2[j].x1=x1;
119             L2[j].x2=x2;
120             L1[j].flag=L2[j].flag=-1;
121             j++;
122         }
123         sort(L1,L1+j);
124         sort(rcy,rcy+j);
125         for(k=0,i=1; i<j; i++)
126             if(rcy[i]!=rcy[k])
127                 rcy[++k]=rcy[i];
128         build(0,k,1);
129         len=0;
130         for(i=0; i<j; i++)
131         {
132             pl=st[1].len;
133             flag=L1[i].flag;
134             update1(L1[i].y1,L1[i].y2,0,k,1);
135             nl=st[1].len;
136             len+=pl>nl?pl-nl:nl-pl;
137         }
138         sort(L2,L2+j);
139         sort(rcx,rcx+j);
140         for(k=0,i=1; i<j; i++)
141             if(rcx[i]!=rcx[k])
142                 rcx[++k]=rcx[i];
143         build(0,k,1);
144         for(i=0; i<j; i++)
145         {
146             pl=st[1].len;
147             flag=L2[i].flag;
148             update2(L2[i].x1,L2[i].x2,0,k,1);
149             nl=st[1].len;
150             len+=pl>nl?pl-nl:nl-pl;
151         }
152         printf("%d\n",len);
153     }
154     return 0;
155 }

 

E题 How Many Buildings

 

维护一个单调栈,注意高度为 0 的情况不能入栈,我在这里WA了好几发

 

参考代码

 

E
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <stack>
 5 
 6 using namespace std;
 7 
 8 stack <int> s;
 9 
10 int main()
11 {
12     int cnt=0, n, a;
13     while(scanf("%d", &n)!=EOF)
14     {
15         int ans=0;
16         while(!s.empty()) s.pop();
17         for(int i=0; i<n; i++)
18         {
19             scanf("%d", &a);
20             while(!s.empty() && s.top()>a)
21             {
22                 ans++;
23                 s.pop();
24             }
25             if(!s.empty() && s.top()<a || s.empty() && a!=0) s.push(a);
26         }
27         while(!s.empty()) s.pop(), ans++;
28         printf("Case %d: %d\n", ++cnt, ans);
29     }
30     return 0;
31 }

 

F题 Cookies Test

 

维护一个大根堆和小根堆,简单的模拟下

 

参考代码

 

F
 1 #include <queue>
 2 #include <iostream>
 3 #include <vector>
 4 #include <cstdio>
 5 #include <cstring>
 6 
 7 using namespace std;
 8 
 9 char s[20];
10 priority_queue <int, vector<int>, less<int> > Min;
11 priority_queue <int, vector<int>, greater<int> > Max;
12 
13 int get()
14 {
15     int sum=0;
16     if(s[0]=='#') return -1;
17     for(int i=0; s[i]; i++) sum=sum*10+s[i]-'0';
18     return sum;
19 }
20 
21 void rebuild()
22 {
23     while(Min.size()<Max.size())
24     {
25         Min.push(Max.top());
26         Max.pop();
27     }
28     while(Min.size()>Max.size())
29     {
30         Max.push(Min.top());
31         Min.pop();
32     }
33 }
34 
35 int main()
36 {
37     while(!Min.empty()) Min.pop();
38     while(!Max.empty()) Max.pop();
39     while(scanf("%s", s)!=EOF)
40     {
41         int val=get();
42         if(val==-1)
43         {
44             printf("%d\n", Max.top());
45             Max.pop();
46             rebuild();
47             continue;
48         }
49         if(Min.empty() || Max.top()>=val) Min.push(val);
50         else if(val>Max.top()) Max.push(val);
51         rebuild();
52     }
53     return 0;
54 }

 

G题 Bracket Sequence

 

线段树好题!把左括号转换成 -1,右括号转换成为 1

一段区间的括号序列是合法的,当且仅当这段区间的和是 0 且部分和的最大值小于等于 0,我把所有的操作分开写了,导致线段树的操作有点多

 

参考代码

 

G
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 using namespace std;
  6 
  7 const int N=100006;
  8 char buff[N];
  9 
 10 struct Interval_Tree
 11 {
 12     struct node
 13     {
 14         int s, t, sum, Max, Min, Set, Rev;
 15         inline void init(int L, int R)
 16         {
 17             s=L, t=R, sum=Max=Min=(buff[L]=='('?-1:1), Set=Rev=0;
 18         }
 19     } T[N<<2];
 20 
 21     inline void pushUp(int id)
 22     {
 23         T[id].sum=T[id<<1].sum+T[id<<1|1].sum;
 24         T[id].Max=max(T[id<<1].Max, T[id<<1].sum+T[id<<1|1].Max);
 25         T[id].Min=min(T[id<<1].Min, T[id<<1].sum+T[id<<1|1].Min);
 26     }
 27 
 28     inline void Set_all(int id, int val)
 29     {
 30         T[id].Set=val, T[id].Rev=0, T[id].sum=(T[id].t-T[id].s+1)*val;
 31         T[id].Min=min(val, T[id].sum), T[id].Max=max(val, T[id].sum);
 32     }
 33 
 34     inline void Rev_all(int id)
 35     {
 36         T[id].Rev^=1, T[id].sum=-T[id].sum;
 37         swap(T[id].Min, T[id].Max);
 38         T[id].Min=-T[id].Min, T[id].Max=-T[id].Max;
 39     }
 40 
 41     inline void pushDown(int id)
 42     {
 43         if(T[id].Set)
 44         {
 45             Set_all(id<<1, T[id].Set), Set_all(id<<1|1, T[id].Set);
 46             T[id].Set=0;
 47         }
 48         if(T[id].Rev)
 49         {
 50             Rev_all(id<<1), Rev_all(id<<1|1);
 51             T[id].Rev=0;
 52         }
 53     }
 54 
 55     void build(int id, int L, int R)
 56     {
 57         T[id].init(L, R);
 58         if(L==R) return;
 59         int mid=(L+R)>>1;
 60         build(id<<1, L, mid), build(id<<1|1, mid+1, R);
 61         pushUp(id);
 62     }
 63 
 64     void Set(int id, int L, int R, int val)
 65     {
 66         if(L<=T[id].s && T[id].t<=R)
 67         {
 68             Set_all(id, val);
 69             return;
 70         }
 71         pushDown(id);
 72         int mid=(T[id].s+T[id].t)>>1;
 73         if(R<=mid) Set(id<<1, L, R, val);
 74         else if(L>mid) Set(id<<1|1, L, R, val);
 75         else Set(id<<1, L, R, val), Set(id<<1|1, L, R, val);
 76         pushUp(id);
 77     }
 78 
 79     void Rev(int id, int L, int R)
 80     {
 81         if(L<=T[id].s && T[id].t<=R)
 82         {
 83             Rev_all(id);
 84             return;
 85         }
 86         pushDown(id);
 87         int mid=(T[id].s+T[id].t)>>1;
 88         if(R<=mid) Rev(id<<1, L, R);
 89         else if(L>mid) Rev(id<<1|1, L, R);
 90         else Rev(id<<1, L, R), Rev(id<<1|1, L, R);
 91         pushUp(id);
 92     }
 93 
 94     void query(int id, int L, int R, int &Max, int &sum)
 95     {
 96         if(L<=T[id].s && T[id].t<=R)
 97         {
 98             Max=T[id].Max;
 99             sum=T[id].sum;
100             return;
101         }
102         pushDown(id);
103         int mid=(T[id].s+T[id].t)>>1;
104         if(R<=mid) query(id<<1, L, R, Max, sum);
105         else if(L>mid) query(id<<1|1, L, R, Max, sum);
106         else
107         {
108             int LMax, Lsum, RMax, Rsum;
109             query(id<<1, L, R, LMax, Lsum);
110             query(id<<1|1, L, R, RMax, Rsum);
111             Max=max(LMax, Lsum+RMax);
112             sum=Lsum+Rsum;
113         }
114         pushUp(id);
115     }
116 } tree;
117 
118 int t, n, m;
119 
120 int main()
121 {
122     scanf("%d", &t);
123     for(int ca=1; ca<=t; ca++)
124     {
125         scanf("%d%s", &n, buff);
126         tree.build(1, 0, n-1);
127         printf("Case %d:\n", ca);
128         scanf("%d", &m);
129         for(int i=0; i<m; i++)
130         {
131             scanf("%s", buff);
132             if(buff[0]=='q')
133             {
134                 int sum, Max, L, R;
135                 scanf("%d%d", &L, &R);
136                 tree.query(1, L, R, Max, sum);
137                 if(Max<=0 && sum==0) printf("YES\n");
138                 else printf("NO\n");
139             }
140             if(buff[0]=='s')
141             {
142                 char s[2];
143                 int L, R;
144                 scanf("%d%d%s", &L, &R, s);
145                 tree.Set(1, L, R, s[0]=='('?-1:1);
146             }
147             if(buff[0]=='r')
148             {
149                 int L, R;
150                 scanf("%d%d", &L, &R);
151                 tree.Rev(1, L, R);
152             }
153         }
154         printf("\n");
155     }
156     return 0;
157 }

 

H题 论程序的阿卡林化

 

由于题目的特殊性:k不变,马上联想到用双端队列来做

 

参考代码

 

H
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <stack>
 5 
 6 using namespace std;
 7 
 8 const int N=200006;
 9 
10 int n, m, k, head, tail, Q[N], flag, len;
11 char name[N][5], s[100];
12 stack <int> ans;
13 
14 void Pop()
15 {
16     if(flag==0)
17     {
18         ans.push(Q[(tail-1+N)%N]);
19         tail=(tail-1+N)%N;
20     }
21     else
22     {
23         ans.push(Q[head]);
24         head=(head+1)%N;
25     }
26     len--;
27 }
28 
29 void Push()
30 {
31     if(flag==0)
32     {
33         Q[(head-1+N)%N]=n;
34         head=(head-1+N)%N;
35     }
36     else
37     {
38         Q[tail]=n;
39         tail=(tail+1)%N;
40     }
41     n++, len++;
42     while(len>k) Pop();
43 }
44 
45 int main()
46 {
47     int cnt=0;
48     while(scanf("%d%d%d", &n, &m, &k)!=EOF)
49     {
50         for(int i=0; i<n; i++) scanf("%s", name[i]);
51         while(!ans.empty()) ans.pop();
52         head=tail=flag=len=0;
53         for(int i=0; i<min(k, n); i++) Q[tail++]=i, len++;
54         for(int i=n-1; i>=k; i--) ans.push(i);
55         for(int i=0; i<m; i++)
56         {
57             scanf("%s", s);
58             if(s[0]=='A')
59             {
60                 for(int j=4; s[j]; j++)
61                 {
62                     name[n][j-4]=s[j];
63                     if(s[j]==')')
64                     {
65                         name[n][j-4]=0;
66                         break;
67                     }
68                 }
69                 Push();
70             }
71             else flag^=1;
72         }
73         while(len>0) Pop();
74         if(cnt!=0) printf("\n");
75         while(!ans.empty())
76         {
77             printf("%s\n", name[ans.top()]);
78             ans.pop();
79         }
80         cnt++;
81     }
82     return 0;
83 }

 

I题 A Simple Problem with Integers

 

线段树僵尸级别的陈题,如果要练习懒操作的话,这是一道很基本的入门题,如果要练习树状数组的话,这是最高级版本的树状数组题目

 

参考代码

 

I
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 typedef long long LL;
 9 const int N=100006;
10 
11 LL data[N];
12 int n, m;
13 
14 struct Interval_Tree
15 {
16     struct node
17     {
18         int s, t;
19         LL sum, lazy;
20         void init(int a, int  b, LL c)
21         {
22             s=a, t=b, sum=c, lazy=0;
23         }
24     } T[N<<2];
25 
26     void build(int id, int L, int R)
27     {
28         T[id].init(L, R, data[L]);
29         if(L==R) return;
30         int mid=(L+R)>>1;
31         build(id<<1, L, mid), build(id<<1|1, mid+1, R);
32         T[id].sum=T[id<<1].sum+T[id<<1|1].sum;
33     }
34 
35     void pushDown(int id)
36     {
37         T[id<<1].lazy+=T[id].lazy;
38         T[id<<1|1].lazy+=T[id].lazy;
39         T[id<<1].sum+=(T[id<<1].t-T[id<<1].s+1)*T[id].lazy;
40         T[id<<1|1].sum+=(T[id<<1|1].t-T[id<<1|1].s+1)*T[id].lazy;
41         T[id].lazy=0;
42     }
43 
44     void update(int id, int L, int R, LL val)
45     {
46         if(L<=T[id].s && T[id].t<=R)
47         {
48             T[id].lazy+=val;
49             T[id].sum+=(T[id].t-T[id].s+1)*val;
50             return;
51         }
52         int mid=(T[id].s+T[id].t)>>1;
53         if(T[id].lazy!=0) pushDown(id);
54         if(R<=mid) update(id<<1, L, R, val);
55         else if(L>mid) update(id<<1|1, L, R, val);
56         else update(id<<1, L, R, val), update(id<<1|1, L, R, val);
57         T[id].sum=T[id<<1].sum+T[id<<1|1].sum;
58     }
59 
60     LL query(int id, int L, int R)
61     {
62         if(L<=T[id].s && T[id].t<=R) return T[id].sum;
63         if(T[id].lazy!=0) pushDown(id);
64         int mid=(T[id].s+T[id].t)>>1;
65         if(R<=mid) return query(id<<1, L, R);
66         else if(L>mid) return query(id<<1|1, L, R);
67         else return query(id<<1, L, R)+query(id<<1|1, L, R);
68     }
69 } tree;
70 
71 char s[2];
72 
73 int main()
74 {
75     scanf("%d%d", &n, &m);
76     for(int i=1; i<=n; i++) scanf("%lld", &data[i]);
77     tree.build(1, 1, n);
78     for(int i=0, a, b, c; i<m; i++)
79     {
80         scanf("%s", s);
81         if(s[0]=='Q')
82         {
83             scanf("%d%d", &a, &b);
84             printf("%lld\n", tree.query(1, a, b));
85         }
86         else
87         {
88             scanf("%d%d%d", &a, &b, &c);
89             tree.update(1, a, b, c);
90         }
91     }
92     return 0;
93 }

 

J题 Never Wait for Weights

 

简单并查集,我的做法是先把所有的数据读入,建好图,根据关系,先求出两个之间的重量差,离线的处理,边处理边合并

 

参考代码

 

J
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 
 7 const int N=100006;
 8 
 9 struct data
10 {
11     int u, val, next;
12     void init(int a, int b, int c)
13     {
14         u=a, val=b, next=c;
15     }
16 } edge[N<<1];
17 int head[N], tot, num, n, m;
18 int weight[N], fa[N];
19 char s[6];
20 
21 struct node
22 {
23     bool flag;
24     int a, b;
25 } query[N];
26 
27 void add_edge(int s, int t, int val)
28 {
29     edge[tot].init(t, val, head[s]);
30     head[s]=tot++;
31 }
32 
33 void DFS(int u, int pre)
34 {
35     for(int e=head[u]; e!=-1; e=edge[e].next)
36     {
37         int v=edge[e].u, val=edge[e].val;
38         if(v==pre || weight[v]!=0x3fffffff) continue;
39         weight[v]=weight[u]+val;
40         DFS(v, u);
41     }
42 }
43 
44 int find_set(int x)
45 {
46     if(x!=fa[x]) fa[x]=find_set(fa[x]);
47     return fa[x];
48 }
49 
50 int main()
51 {
52     while(scanf("%d%d", &n, &m), n!=0 || m!=0)
53     {
54         tot=num=0;
55         memset(head, -1, sizeof head);
56         for(int i=0, a, b, c; i<m; i++)
57         {
58             scanf("%s", s);
59             if(s[0]=='!')
60             {
61                 scanf("%d%d%d", &a, &b, &c);
62                 add_edge(a, b, c);
63                 add_edge(b, a, -c);
64                 query[num].a=a, query[num].b=b;
65                 query[num].flag=0;
66                 num++;
67             }
68             else
69             {
70                 scanf("%d%d", &query[num].a, &query[num].b);
71                 query[num].flag=1;
72                 num++;
73             }
74         }
75         for(int i=1; i<=n; i++) weight[i]=0x3fffffff;
76         for(int i=1; i<=n; i++)
77             if(weight[i]==0x3fffffff)
78             {
79                 weight[i]=0;
80                 DFS(i, -1);
81             }
82         for(int i=1; i<=n; i++) fa[i]=i;
83         for(int i=0; i<m; i++)
84         {
85             int f1=find_set(query[i].a);
86             int f2=find_set(query[i].b);
87             if(query[i].flag)
88             {
89                 if(f1==f2) printf("%d\n", weight[query[i].b]-weight[query[i].a]);
90                 else printf("UNKNOWN\n");
91             }
92             else
93             {
94                 if(f1!=f2) fa[f1]=f2;
95             }
96         }
97     }
98     return 0;
99 }

 

K题 种蘑菇的魔理沙

 

和 I 题一样的僵尸级别的线段树陈题,区间最大值

 

参考代码

 

K
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 typedef long long LL;
 8 const int N=1000006;
 9 
10 LL data[N];
11 int n, m;
12 
13 struct Interval_Tree
14 {
15     struct node
16     {
17         int s, t;
18         LL Max, lazy;
19         void init(int a, int b, LL c)
20         {
21             s=a, t=b, Max=c, lazy=0;
22         }
23     } T[N<<2];
24 
25     void build(int id, int L, int R)
26     {
27         T[id].init(L, R, data[L]);
28         if(L==R) return;
29         int mid=(L+R)>>1;
30         build(id<<1, L, mid), build(id<<1|1, mid+1, R);
31         T[id].Max=max(T[id<<1].Max, T[id<<1|1].Max);
32     }
33 
34     void pushDown(int id)
35     {
36         T[id<<1].lazy+=T[id].lazy;
37         T[id<<1|1].lazy+=T[id].lazy;
38         T[id<<1].Max+=T[id].lazy;
39         T[id<<1|1].Max+=T[id].lazy;
40         T[id].lazy=0;
41     }
42 
43     void update(int id, int L, int R, LL val)
44     {
45         if(L<=T[id].s && T[id].t<=R)
46         {
47             T[id].Max+=val;
48             T[id].lazy+=val;
49             return;
50         }
51         if(T[id].lazy!=0) pushDown(id);
52         int mid=(T[id].s+T[id].t)>>1;
53         if(R<=mid) update(id<<1, L, R, val);
54         else if(L>mid) update(id<<1|1, L, R, val);
55         else update(id<<1, L, R, val), update(id<<1|1, L, R, val);
56         T[id].Max=max(T[id<<1].Max, T[id<<1|1].Max);
57     }
58 
59     LL query(int id, int L, int R)
60     {
61         if(L<=T[id].s && T[id].t<=R) return T[id].Max;
62         if(T[id].lazy) pushDown(id);
63         int mid=(T[id].s+T[id].t)>>1;
64         if(R<=mid) return query(id<<1, L, R);
65         else if(L>mid) return query(id<<1|1, L, R);
66         else return max(query(id<<1, L, R), query(id<<1|1, L, R));
67     }
68 } tree;
69 
70 int main()
71 {
72     scanf("%d", &n);
73     for(int i=1; i<=n; i++) scanf("%lld", data+i);
74     tree.build(1, 1, n);
75     scanf("%d", &m);
76     for(int i=0, a, s, t; i<m; i++)
77     {
78         LL val;
79         scanf("%d", &a);
80         if(a==1)
81         {
82             scanf("%d%d", &s, &t);
83             if(s>t) swap(s, t);
84             if(s<1) s=1;
85             if(t>n) t=n;
86             printf("%lld\n", tree.query(1, s, t));
87         }
88         else
89         {
90             scanf("%d%d%lld", &s, &t, &val);
91             if(s>t) swap(s, t);
92             if(s<1) s=1;
93             if(t>n) t=n;
94             tree.update(1, s, t, val);
95         }
96     }
97     return 0;
98 }

 

L题 中二少女与字符串

 

把所有的字符串的后缀添加进字典树中,然后该怎么做就怎么做了

 

参考代码

 

L
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 const int N=4000006;
 9 
10 char buff[2000], s[30];
11 int Max, t;
12 
13 struct Trie
14 {
15     struct node
16     {
17         int next[26], cnt;
18         void init()
19         {
20             for(int i=0; i<26; i++) next[i]=-1;
21             cnt=0;
22         }
23     } trie[N];
24     int num, ans;
25 
26     void Insert(int s)
27     {
28         int u=0;
29         for(int i=s; buff[i]; i++)
30         {
31             int id=buff[i]-'a';
32             if(trie[u].next[id]==-1)
33             {
34                 trie[num].init();
35                 trie[u].next[id]=num++;
36             }
37             u=trie[u].next[id];
38         }
39     }
40 
41     void deal(int u, int res)
42     {
43         if(res>Max) return;
44         if(u!=0) ans++;
45         for(int i=0; i<26; i++)
46         {
47             if(trie[u].next[i]==-1) continue;
48             deal(trie[u].next[i], res+((s[i]-'0')^1));
49         }
50     }
51 } tree;
52 
53 int main()
54 {
55     scanf("%d", &t);
56     while(t--)
57     {
58         scanf("%s%s%d", buff, s, &Max);
59         tree.ans=tree.num=0;
60         tree.trie[tree.num++].init();
61         for(int i=0; buff[i]; i++)
62             tree.Insert(i);
63         tree.deal(0, 0);
64         printf("%d\n", tree.ans);
65     }
66     return 0;
67 }

 

M题 Islands

 

并查集僵尸级别的题目,还是离线处理,不过需要把所有的高度排个序,不然会T

 

参考代码

 

 

M
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 const int zl[4][2]={-1, 0, 1, 0, 0, 1, 0, -1};
 9 
10 struct node
11 {
12     int x, y, H;
13     bool operator <(const node &temp) const
14     {
15         return H>temp.H;
16     }
17 } h[1000006];
18 int Z, n, m, T, cur;
19 int water[100006], ans[100006], Map[1006][1006], fa[1000006];
20 
21 inline bool in(int x, int y)
22 {
23     return x>=0 && x<n && y>=0 && y<m;
24 }
25 
26 int find_set(int x)
27 {
28     if(x!=fa[x]) fa[x]=find_set(fa[x]);
29     return fa[x];
30 }
31 
32 int main()
33 {
34     scanf("%d", &Z);
35     while(Z--)
36     {
37         scanf("%d%d", &n, &m);
38         for(int i=0; i<n; i++)
39             for(int j=0; j<m; j++)
40             {
41                 scanf("%d", &Map[i][j]);
42                 h[i*m+j].x=i, h[i*m+j].y=j, h[i*m+j].H=Map[i][j];
43                 fa[i*m+j]=i*m+j;
44             }
45         sort(h, h+n*m);
46         scanf("%d", &T);
47         for(int i=0; i<T; i++) scanf("%d", &water[i]);
48         ans[T]=0, cur=0;
49         for(int i=T-1; i>=0; i--)
50         {
51             ans[i]=ans[i+1];
52             for(; cur<n*m && h[cur].H>water[i]; cur++)
53             {
54                 ans[i]++;
55                 for(int k=0; k<4; k++)
56                 {
57                     int x=h[cur].x+zl[k][0];
58                     int y=h[cur].y+zl[k][1];
59                     if(!in(x, y)) continue;
60                     if(Map[x][y]<=water[i]) continue;
61                     int u=h[cur].x*m+h[cur].y;
62                     int v=x*m+y;
63                     int f1=find_set(u);
64                     int f2=find_set(v);
65                     if(f1!=f2)
66                     {
67                         ans[i]--;
68                         fa[f1]=f2;
69                     }
70                 }
71             }
72         }
73         for(int i=0; i<T; i++) printf("%d ", ans[i]);
74         printf("\n");
75     }
76     return 0;
77 }

 

 

N题 贪玩的xie

 

某场 CF 原题,好像是 Div2 的 E

可以先离散化,然后再利用线段树维护地雷的信息,简单但不易想到的公式:res=res1+res2+sum2*cnt1-sum1*cnt2

 

参考代码

 

N
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <map>
  6 #include <cstring>
  7 
  8 using namespace std;
  9 
 10 const int N=400006;
 11 typedef long long LL;
 12 
 13 vector <LL> val;
 14 map<LL, int> ihash;
 15 map<int, LL> iback;
 16 LL x[N], old[N];
 17 int t, n, m;
 18 struct data
 19 {
 20     int flag;
 21     LL a, b;
 22 } op[N];
 23 
 24 struct node
 25 {
 26     int s, t;
 27     LL cnt, sum, res;
 28     void init(int L, int R)
 29     {
 30         s=L, t=R, cnt=sum=res=0ll;
 31     }
 32 } ans;
 33 
 34 struct Interval_Tree
 35 {
 36     node T[N<<2];
 37     void build(int id, int L, int R)
 38     {
 39         T[id].init(L, R);
 40         if(L==R) return;
 41         int mid=(L+R)>>1;
 42         build(id<<1, L, mid), build(id<<1|1, mid+1, R);
 43     }
 44 
 45     inline void pushUp(node &fa, node &L, node &R)
 46     {
 47         fa.res=L.res+R.res+R.sum*L.cnt-L.sum*R.cnt;
 48         fa.sum=L.sum+R.sum;
 49         fa.cnt=L.cnt+R.cnt;
 50     }
 51 
 52     void Delete(int id, int pos)
 53     {
 54         if(T[id].s==T[id].t)
 55         {
 56             T[id].cnt=T[id].sum=T[id].res=0;
 57             return;
 58         }
 59         int mid=(T[id].s+T[id].t)>>1;
 60         if(pos<=mid) Delete(id<<1, pos);
 61         else Delete(id<<1|1, pos);
 62         pushUp(T[id], T[id<<1], T[id<<1|1]);
 63     }
 64 
 65     void Insert(int id, int pos)
 66     {
 67         if(T[id].s==T[id].t)
 68         {
 69             T[id].cnt=1, T[id].sum=iback[pos], T[id].res=0;
 70             return;
 71         }
 72         int mid=(T[id].s+T[id].t)>>1;
 73         if(pos<=mid) Insert(id<<1, pos);
 74         else Insert(id<<1|1, pos);
 75         pushUp(T[id], T[id<<1], T[id<<1|1]);
 76     }
 77 
 78     node query(int id, int L, int R)
 79     {
 80         if(L<=T[id].s && T[id].t<=R) return T[id];
 81         int mid=(T[id].s+T[id].t)>>1;
 82         if(R<=mid) return query(id<<1, L, R);
 83         else if(L>mid) return query(id<<1|1, L, R);
 84         node sL=query(id<<1, L, R), sR=query(id<<1|1, L, R), fa;
 85         pushUp(fa, sL, sR);
 86         return fa;
 87     }
 88 } tree;
 89 
 90 int main()
 91 {
 92     scanf("%d", &t);
 93     for(int ca=1; ca<=t; ca++)
 94     {
 95         val.clear();
 96         scanf("%d", &n);
 97         old[0]=n;
 98         for(int i=1; i<=n; i++)
 99         {
100             scanf("%lld", &x[i]);
101             old[i]=x[i];
102             val.push_back(x[i]);
103         }
104         scanf("%d", &m);
105         for(int i=0; i<m; i++)
106         {
107             scanf("%d%lld%lld", &op[i].flag, &op[i].a, &op[i].b);
108             if(op[i].flag==1)
109             {
110                 x[op[i].a]+=op[i].b;
111                 val.push_back(x[op[i].a]);
112             }
113             else
114             {
115                 val.push_back(op[i].a);
116                 val.push_back(op[i].b);
117             }
118         }
119         sort(val.begin(), val.end());
120         ihash.clear(), iback.clear(), n=0;
121         for(vector<LL>::iterator it=val.begin(); it!=val.end(); it++)
122         {
123             if(ihash.find(*it)!=ihash.end()) continue;
124             ihash.insert(make_pair(*it, ++n));
125             iback.insert(make_pair(n, *it));
126         }
127         tree.build(1, 1, n);
128         for(int i=1; i<=old[0]; i++) tree.Insert(1, ihash[old[i]]);
129         for(int i=0; i<m; i++)
130         {
131             if(op[i].flag==1)
132             {
133                 tree.Delete(1, ihash[old[op[i].a]]);
134                 old[op[i].a]+=op[i].b;
135                 tree.Insert(1, ihash[old[op[i].a]]);
136             }
137             else
138             {
139                 ans=tree.query(1, ihash[op[i].a], ihash[op[i].b]);
140                 printf("%lld\n", ans.res);
141             }
142         }
143     }
144     return 0;
145 }

 

 

 

posted @ 2013-05-13 15:44  jianzhang.zj  阅读(699)  评论(0编辑  收藏  举报