zoukankan      html  css  js  c++  java
  • 【ContestHunter】【弱省胡策】【Round6】

    KMP/DP+树链剖分+线段树/暴力


      今天考的真是……大起大落……

    String

      QwQ题意理解又出错了……(还是说一开始理解了,后来自己又忘了为什么是这样了?)

      反正最后的结果就是……我当成:后面每行只需要和第一行check一下就可以了。

      因为那个图真的很像在搞串的匹配啊……一格一格往过移,看能不能匹配

      然后不就是每个s[i]对A取一下模,然后KMP?看有多少个位置能匹配咯。。。

      (其实这是A=B时的做法)

      将原序列增长一倍(复制一遍),对A取模做一遍,然后再对B取模做一遍,看有哪些位置是合法的,统计一下……

      然而其实正解可以证明出来当$A ot = B$的时候,可以当A=B做……也就是说,上面那种做法……是可以AC的-_-b

      P.S.正解是KMP来找循环节= = n如果可以整除n-next[n],那么循环节长度就是n-next[n]……可匹配长度就是……那么多……啊反正差不多啦

     1 //Round6 A
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<algorithm>
     7 #define rep(i,n) for(int i=0;i<n;++i)
     8 #define F(i,j,n) for(int i=j;i<=n;++i)
     9 #define D(i,j,n) for(int i=j;i>=n;--i)
    10 #define pb push_back
    11 using namespace std;
    12 typedef long long LL;
    13 inline int getint(){
    14     int r=1,v=0; char ch=getchar();
    15     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
    16     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
    17     return r*v;
    18 }
    19 const int N=2000010;
    20 /*******************template********************/
    21 
    22 
    23 int a[N],b[N],c[N],A,B,n,ans,nxt[N];
    24 bool yes[N];
    25 void init(){
    26     n=getint(); A=getint(); B=getint();
    27     F(i,1,n) a[i]=getint();
    28     memset(yes,0,sizeof yes);
    29     ans=0;
    30 }
    31 void KMP(int *s,int n){
    32     int m=n*2;
    33     nxt[1]=0; int j=0;
    34     F(i,2,n+1){
    35         while(j && s[i]!=s[j+1]) j=nxt[j];
    36         if (s[i]==s[j+1]) j++;
    37         nxt[i]=j;
    38     }
    39     j=0;
    40     F(i,2,m-1){
    41         while(j && b[i]!=s[j+1]) j=nxt[j];
    42         if (b[i]==s[j+1]) j++;
    43         if (j==n) yes[i]=1,j=nxt[j];
    44     }
    45 }
    46 void work(){
    47     F(i,1,n) c[i]=b[i]=b[i+n]=a[i]%A;
    48     KMP(c,n);
    49     if (A!=B){
    50         F(i,1,n) c[i]=b[i]=b[i+n]=a[i]%B;
    51         KMP(c,n);
    52     }
    53     F(i,n,n*2-1) ans+=yes[i];
    54     printf("%d
    ",ans?ans+1:0);
    55 }
    56 int main(){
    57     int T=getint();
    58     while(T--){
    59         init();
    60         work();
    61     }
    62     return 0;
    63 }
    View Code

    Tree

      ……30分的做法其实就是直接TreeDP,40~50的做法是线段树维护最大连续子段和,那么满分做法?两者结合……Orzzzzzz

      所以就是树链剖分+DP(并没有?其实是贪心?)啊……

      Orz zyf,这题代码感觉细节很多啊……

      树链剖分一下,权值沿轻链按TreeDP的思路将权值加到fa上面,建出整个线段树……

      然后每次修改的时候,先将这个点x到top[x]这一条重链上的ans更新一下(这里重点是maxl,即从左端点开始的最大连续子段和),然后!更新fa[top[x]]的DP值!因为它在线段树上的权值是自身权值+轻链的maxl,怎么搞?区间查询一下top[x]所在的重链的maxl……然后更新。。。【这里我并不知道如何记重链的结尾……因为dfs序记start和end是子树的,所以并不能那样搞。。。zyf的做法是:往出连轻链的时候多++一下dfs_clock,这样就可以将不同的重链断开,(当然是将这些没有编号的空节点的权值置为-INF)

      查询的时候……直接出解呗。。。

      1 //Round6 B
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<iostream>
      6 #include<algorithm>
      7 #define rep(i,n) for(int i=0;i<n;++i)
      8 #define F(i,j,n) for(int i=j;i<=n;++i)
      9 #define D(i,j,n) for(int i=j;i>=n;--i)
     10 #define pb push_back
     11 using namespace std;
     12 typedef long long LL;
     13 inline int getint(){
     14     int r=1,v=0; char ch=getchar();
     15     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
     16     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
     17     return r*v;
     18 }
     19 const int N=500010,INF=1000000000;
     20 /*******************template********************/
     21 
     22 int head[N],to[N],nxt[N],cnt;
     23 void add(int x,int y){
     24     to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt;
     25     to[++cnt]=x; nxt[cnt]=head[y]; head[y]=cnt;
     26 }
     27 
     28 int n,m,f[N],id[N],v[N],ans;
     29 int pos[N],dfs_clock,fa[N],son[N],size[N],top[N];
     30 struct node{
     31    int max,maxl,maxr;
     32    LL sum;
     33 }t[N];
     34 bool vis[N];
     35 
     36 void dfs(int x){
     37     size[x]=1; son[x]=0;
     38     int mx=0;
     39     for(int i=head[x];i;i=nxt[i])
     40         if (to[i]!=fa[x]){
     41             fa[to[i]]=x;
     42             dfs(to[i]);
     43             size[x]+=size[to[i]];
     44             if (size[to[i]]>mx) son[x]=to[i],mx=size[to[i]];
     45         }
     46 }
     47 void connect(int x,int f){
     48     pos[x]=++m; top[x]=f; vis[x]=1;
     49     id[m]=x;
     50     if (son[x]) connect(son[x],f);
     51     for(int i=head[x];i;i=nxt[i])
     52         if (!vis[to[i]])
     53             ++m,connect(to[i],to[i]);
     54 }
     55 
     56 #define L (o<<1)
     57 #define R (o<<1|1)
     58 #define mid (l+r>>1)
     59 node maintain(node a,node b){
     60     node ans;
     61     ans.maxl=max((LL)a.maxl,a.sum+b.maxl);
     62     ans.maxr=max((LL)b.maxr,b.sum+a.maxr);
     63     ans.max=max(a.maxr+b.maxl,max(a.max,b.max));
     64     ans.sum=a.sum+b.sum;
     65     return ans;
     66 }
     67 void update(int o,int l,int r,int p,int v){
     68     if (l==r){
     69         t[o].sum+=v;
     70         t[o].maxl=t[o].maxr=t[o].max=max(t[o].sum,(LL)0);
     71     }else{
     72         if (p<=mid) update(L,l,mid,p,v);
     73         else update(R,mid+1,r,p,v);
     74         t[o]=maintain(t[L],t[R]);
     75     }
     76 }
     77 node query(int o,int l,int r,int ql,int qr){
     78     if (l==ql && r==qr) return t[o];
     79     else if (qr<=mid) return query(L,l,mid,ql,qr);
     80     else if (ql>mid) return query(R,mid+1,r,ql,qr);
     81     else return maintain(query(L,l,mid,ql,mid),query(R,mid+1,r,mid+1,qr));
     82 }
     83 void change(int x,int y1,int y2){
     84     while(x){
     85         int y=top[x],z=query(1,1,m,pos[y],m).maxl;
     86         update(1,1,m,pos[x],y2-y1);
     87         y1=z; y2=query(1,1,m,pos[y],m).maxl;
     88         x=fa[top[x]];
     89     }
     90 }
     91 
     92 int main(){
     93 #ifndef ONLINE_JUDGE
     94     freopen("sub.in","r",stdin);
     95     freopen("sub.out","w",stdout);
     96 #endif
     97     n=getint(); int T=getint();
     98     F(i,1,n) v[i]=getint();
     99     F(i,2,n){
    100         int x=getint(),y=getint();
    101         add(x,y);
    102     }
    103     dfs(1); connect(1,1);
    104     F(i,1,m) if (!id[i]) update(1,1,m,i,-INF);
    105     F(i,1,n) change(i,0,v[i]);
    106     while(T--){
    107         int cmd=getint(),x,y;
    108         if (cmd==1){
    109             x=getint(), y=getint();
    110             change(x,v[x],y);
    111             v[x]=y;
    112         }else printf("%d
    ",t[1].max);
    113     }
    114     return 0;
    115 }
    View Code

    Transport

      ……我就无语了……

      一开始我想的是二分!然后模拟过程进行判断!然而连样例都过不了……QwQ

      仔细想了想好像确实并不满足单调性……会有小的波动……

      然后蒟蒻就不会了……实在没办法了,二分的时候边界不是 $L=max{a[i]},R=sum a[i]$ 嘛= =然后我就直接将二分的过程删掉……改成枚举……然后……TM居然就过了……maya我也是惊呆了,这个枚举的上下界明明很大的好吗……如果全都走一遍肯定要T的啊!然而我就是过了……就是这么神奇……>_>

      P.S.这个边界 L 还是比较松的,其实应该弄成$max{ frac{sum a[i]}{k}, max(a[i]) }$ ?

     1 //Round6 C
     2 #include<cstdio>
     3 #include<set>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<iostream>
     7 #include<algorithm>
     8 #define rep(i,n) for(int i=0;i<n;++i)
     9 #define F(i,j,n) for(int i=j;i<=n;++i)
    10 #define D(i,j,n) for(int i=j;i>=n;--i)
    11 #define pb push_back
    12 using namespace std;
    13 typedef long long LL;
    14 inline int getint(){
    15     int r=1,v=0; char ch=getchar();
    16     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
    17     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
    18     return r*v;
    19 }
    20 const int N=100010;
    21 /*******************template********************/
    22 
    23 int n,k,a[N],sum;
    24 multiset<int>s,s2;
    25 multiset<int>::iterator it;
    26 bool check(int c){
    27     if (k*c<sum) return 0;
    28     s2=s;
    29     int num;
    30     F(i,1,k){
    31         num=c;
    32         do{
    33             if (s2.empty()) return 1;
    34             it=s2.lower_bound(num);
    35             if (it==s2.end()) it--;
    36             if (*it>num){
    37                 if (it==s2.begin()) break;
    38                 else it--;
    39             }
    40             num-=*it;
    41             s2.erase(it);
    42         }while(1);
    43     }
    44     return s2.empty();
    45 }
    46 void init(){
    47     n=getint(); k=getint();
    48     s.clear();
    49     int L=0,R=0;
    50     sum=0;
    51     F(i,1,n){
    52         a[i]=getint();
    53         sum+=a[i]; R+=a[i]; L=max(L,a[i]);
    54         s.insert(a[i]);
    55     }
    56     F(i,L,R)
    57         if (check(i)){
    58             printf("%d
    ",i);
    59             return;
    60         }
    61 }
    62 
    63 int main(){
    64 #ifndef ONLINE_JUDGE
    65     freopen("C.in","r",stdin);
    66     freopen("C.out","w",stdout);
    67 #endif
    68     int T=getint();
    69     while(T--) init();
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    vim的额外功能
    vi的使用
    文件与文件系统的压缩
    其他常用的压缩与备份工具
    光盘写入工具
    XFS 文件系统的备份与还原
    打包命令:tar
    Linux 系统常见的压缩命令
    Windows10修改DNS
    Linux 磁盘与文件系统管理
  • 原文地址:https://www.cnblogs.com/Tunix/p/4581686.html
Copyright © 2011-2022 走看看