zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    zhcon安装过程记录
    diff和patch配合使用(转载备用)
    Linux /etc/passwd 和 /etc/group 文件格式
    APT 常用功能
    Linux邮件服务器架构
    出现segment fault 错误的几种原因
    位运算
    Linux启动过程中几个重要配置文件的执行过程
    2016-2017 ACM-ICPC, South Pacific Regional Contest (SPPC 16)
    Codeforces Round #439 (Div. 2) 题解
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3075872.html
Copyright © 2011-2022 走看看