NOI2015

D1T1

并查集。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b)  for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxN=100000;
const int maxcnt=2*maxN;

int N;
struct Ta{int e,x,y;}a[maxN+100];
int cnt,bak[maxcnt+100];

int pa[maxcnt+100];
inline int findroot(int a){return pa[a]<0?a:pa[a]=findroot(pa[a]);}
inline void BCJ_Union(int a,int b)
  {
      int f1=findroot(a),f2=findroot(b);
      if(f1==f2)return;
      if(pa[f1]>pa[f2])swap(f1,f2);
      pa[f1]=pa[f1]+pa[f2];
      pa[f2]=f1;
  }

int main()
  {
      freopen("prog.in","r",stdin);
      freopen("prog.out","w",stdout);
      int i;
      for(int Case=gint();Case;Case--)
        {
            N=gint();
            re(i,1,N){a[i].x=gint();a[i].y=gint();a[i].e=gint();}
            cnt=0;
            re(i,1,N){bak[++cnt]=a[i].x;bak[++cnt]=a[i].y;}
            sort(bak+1,bak+cnt+1);
            cnt=unique(bak+1,bak+cnt+1)-bak-1;
            re(i,1,N){a[i].x=lower_bound(bak+1,bak+cnt+1,a[i].x)-bak;a[i].y=lower_bound(bak+1,bak+cnt+1,a[i].y)-bak;}
            re(i,1,cnt)pa[i]=-1;
            re(i,1,N)if(a[i].e==1)BCJ_Union(a[i].x,a[i].y);
            int flag=1;
            re(i,1,N)if(a[i].e==0 && findroot(a[i].x)==findroot(a[i].y)){flag=0;break;}
            if(flag)PF("YES
");else PF("NO
");
        }
      return 0;
  }
View Code

D1T2

树链剖分+线段树。

树链剖分中,我们在求边的编号的时候,我们可以用DFS,虽然这样麻烦一点,但是可以保证同一棵子树的编号在线段树中是连续的。

但考试的时候并没有想到这一点。

然后用了LCT,打了8KB,我都不想说话了。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b)  for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxN=100000;
const int maxQ=100000;

struct Tnode
  {
      Tnode *fa,*son[2],*path_parent;
      int R,L,val,add;
      inline Tnode(){fa=son[0]=son[1]=path_parent=0;R=L=val=add=0;}
      inline void down()
        {
            if(add!=0)
              {
                  if(son[0]){son[0]->val+=add;son[0]->add+=add;}
                  if(son[1]){son[1]->val+=add;son[1]->add+=add;}
                  add=0;
              }
        }
  };

int N,Q;
int fa[maxN+100];
int now,first[maxN+100];
struct Tedge{int v,next;}edge[maxN+100];
int dep[maxN+100];
int jump[maxN+100][31];
Tnode *pos[maxN+100];

inline void addedge(int u,int v)
  {
      now++;
      edge[now].v=v;
      edge[now].next=first[u];
      first[u]=now;
  }

int head,tail,que[maxN+100];
int size[maxN+100],heavy[maxN+100],top[maxN+100],w[maxN+100],cnt;
inline void BFS()
  {
      int i,j,u,v;
      dep[que[head=tail=1]=1]=1;
      while(head<=tail)
        {
            u=que[head++];
            for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)dep[que[++tail]=v]=dep[u]+1;
        }
      re(i,1,tail)
        {
            u=que[i];
            jump[u][0]=fa[u];
            re(j,1,30)jump[u][j]=jump[jump[u][j-1]][j-1];
        }
      red(j,tail,1)
        {
            u=que[j];
            size[u]=1;
            heavy[u]=-1;
            for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)
              {
                  size[u]+=size[v];
                  if(heavy[u]==-1 || size[v]>size[heavy[u]])heavy[u]=v;
              }
        }
      top[1]=1;
      re(i,2,tail)
        {
              u=que[i];
            if(heavy[fa[u]]==u) top[u]=top[fa[u]]; else top[u]=u;
        }
      mmst(w,-1);
      cnt=0;
      re(i,1,tail)
        {
            u=que[i];
            if(w[u]!=-1)continue;
            int r=u;
            while(r!=-1){w[r]=++cnt;r=heavy[r];}
        }
  };

int tree[4*maxN+100];
inline void down(int root)
  {
      if(tree[root]!=0)
        {
            tree[root*2]=tree[root*2+1]=tree[root];
            tree[root]=0;
        }
  }
inline void update(int root,int l,int r,int x,int y,int val)
  {
      if(l>r || x>y || r<x || y<l) return;
      if(x<=l && r<=y){tree[root]=val;return;}
      down(root);
      int mid=(l+r)/2;
      update(root*2,l,mid,x,y,val);
      update(root*2+1,mid+1,r,x,y,val);
  }
inline int ask(int root,int l,int r,int x)
  {
      if(l<=x && x<=r && tree[root]!=0) return tree[root];
      if(x<=l && r<=x) return tree[root];
      down(root);
      int mid=(l+r)/2;
      if(x<=mid) return ask(root*2,l,mid,x); else return ask(root*2+1,mid+1,r,x);
  }
inline void Cover(int a,int b,int val)
  {
      int f1=top[a],f2=top[b];
      while(f1!=f2)
        {
            if(dep[f1]<dep[f2]){swap(f1,f2);swap(a,b);}
            update(1,1,cnt,w[f1],w[a],val);
            a=fa[f1];
            f1=top[a];
        }
      if(dep[a]>dep[b])swap(a,b);
      update(1,1,cnt,w[a],w[b],val);
  }
inline Tnode *findp(int x)
  {
      if(x==0) return pos[0];
      x=ask(1,1,cnt,w[x]);
      return (x==0)?0:pos[x];
  }

inline void Splay_Rotate(Tnode *x,int flag)
  {
      Tnode *y=x->fa,*z=y->fa;
      y->son[flag^1]=x->son[flag];if(x->son[flag])x->son[flag]->fa=y;
      x->son[flag]=y;y->fa=x;
      x->path_parent=y->path_parent;y->path_parent=0;
      x->fa=z;if(z)z->son[(y==z->son[1])]=x;
  }
inline void Splay(Tnode *x)
  {
      Tnode *y,*z;
      while(x->fa)
        {
            y=x->fa;z=y->fa;
            if(z)z->down();y->down();x->down();
            if(!z){Splay_Rotate(x,x==y->son[0]);return;}
            int L=(x==y->son[0]),R=(y==z->son[0]);
            if(L==R){Splay_Rotate(y,L);Splay_Rotate(x,R);continue;}
            if(L!=R){Splay_Rotate(x,L);Splay_Rotate(x,R);continue;}
        }
      x->down();
  }
inline void LCT_Access(Tnode *x)
  {
      Tnode *y;
      for(y=0;x;y=x,x=x->path_parent)
        {
            Splay(x);
            if(x->son[1]){x->son[1]->fa=0;x->son[1]->path_parent=x;}
            x->son[1]=y;
            if(y){y->fa=x;y->path_parent=0;}
        }
  }
inline void LCT_update(Tnode *x,int v)
  {
      LCT_Access(x);
      Splay(x);
      x->val+=v;
      x->add+=v;
      x->down();
  }
inline void LCT_Delete(Tnode *u,Tnode *v)
  {
      LCT_Access(u);
      LCT_Access(v);
      u->path_parent=0;
  }
inline int swim(int x,int H)
  {
      int res=x;
      for(int i=0;H!=0;H/=2,i++)if(H&1)res=jump[res][i];
      return res;
  }
inline void LCT_Fen(Tnode *x,int ca)
  {
      int R,L,G;
      Tnode *p;
      if(ca==x->R)return;
      R=x->R;
      L=x->L;
      G=swim(R,dep[R]-dep[ca]-1);
      p=findp(fa[L]);
      LCT_Delete(x,p);
      pos[ca]=new Tnode;
      pos[ca]->path_parent=p;
      pos[ca]->R=ca;
        pos[ca]->L=L;
      pos[ca]->val=x->val;
      Cover(ca,L,ca);
      x->path_parent=pos[ca];
      x->L=G;
      x->val-=dep[ca]-dep[L]+1;
  }

inline int isblack(int x)
  {
      Tnode *p=findp(x);
      if(!p)return 0;
      LCT_Access(p);
      Splay(p);
      Tnode *t=p;t->down();
      while(t->son[0]){t=t->son[0];t->down();}
      return t==pos[0];
  }

inline int findL(int x)
  {
      int i;
      red(i,30,0)if(jump[x][i]!=0 && !isblack(jump[x][i])) x=jump[x][i];
      return x;
  }

int main()
  {
      freopen("manager.in","r",stdin);
      freopen("manager.out","w",stdout);
      int i;
      N=gint();
      now=-1;mmst(first,-1);
      re(i,2,N)
          {
              fa[i]=gint()+1;
              addedge(fa[i],i);
            }
      BFS();
      pos[0]=new Tnode;
      Q=gint();
      while(Q--)
        {
            char s[20];int x,ca,R,L;
            Tnode *p;
            SF("%s%d
",s,&x);x++;
            switch(s[0])
              {
                  case 'i':
                      if(isblack(x)){PF("0
");continue;}
                      L=findL(x);
                      ca=fa[L];
                      p=findp(ca);
                      LCT_Fen(p,ca);
                      pos[x]=new Tnode;
                      pos[x]->R=x;pos[x]->L=L;
                      Cover(x,L,x);
                      pos[x]->path_parent=findp(ca);
                      LCT_update(pos[x],dep[x]-dep[ca]);
                      PF("%d
",dep[x]-dep[ca]);
                  break;
                  case 'u':
                      if(!isblack(x)){PF("0
");continue;}
                      p=findp(x);
                      R=p->R;
                            L=p->L;
                            ca=fa[L];
                      PF("%d
",p->val-(dep[x]-dep[L]));
                      LCT_update(p,-p->val);
                            LCT_Delete(p,findp(ca));
                            //////////
                            if(x==L)continue;
                            x=fa[x];
                            pos[x]=new Tnode;
                      pos[x]->R=x;pos[x]->L=L;
                      Cover(x,L,x);
                      pos[x]->path_parent=findp(ca);
                      LCT_update(pos[x],dep[x]-dep[ca]);
                  break;
              }
        }
      return 0;
  }
View Code

D1T3

背包+状压DP。

神题。。。。。。

ppt讲得比较清晰了。

30%的做法:

集合A和集合B互质就是没有包含相同的质因数,我们将每个数分解质因数。

分解质因数求出每个数包含哪些质因子,使用二进制状态压缩,存在s[i]里,每个数看作一个物品,做一次二进制状态的背包DP。

容易得到g[j|s[i]]=(g[j|s[i]]+g[j])%Mod

这是一个背包,所以j倒序循环。

100%的做法:

注意到小于等于sqrt(N)的质因数最多只有9个,每一个数最多包含一个大于sqrt(N)的质因数。

s[i]就表示i在2...sqrt(N)中包含哪些质因子,使用二进制状态压缩。

f(i)[x][y]表示可以使用前i个大质数和全部小质数,A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制)时的方案数。

容易得到初值f(0)[x][y]=g[x]*g[y]%Mod,其中x&y==0。

其中i这一维可以在背包中忽略。

转移时,枚举包含第i个大质数的所有整数z,他们可以某些且至少一个分配在A集合,可以某些且至少一个分配在B集合,也可以全部丢弃不用。单是绝对不可以某些分配在A集合,某些分配在B集合。

我们在做第i个大质数的时候,记d[x][y][0]表示A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制),包含第i个大质数的所有至少一个整数z都分配在A集合中的方案数。

同理,d[x][y][0]表示A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制),包含第i个大质数的某些且至少一个整数z都分配在B集合中的方案数。

分给A:d[x|s[z]][y][0]=(d[x|s[z]][y][0]+d[x][y][0]+f[x][y])%Mod

分给B:d[x][y|s[z]][1]=(d[x][y|s[z]][1]+d[x][y][0]+f[x][y])%Mod

这是一个背包,所以x和y倒序循环。

至于为什么还要加上一个f[x][y],因为d[x][y][0]是前面用了至少一个整数z,但是有可能前面没有用整数z,用了当前的整数z,所以要加f[x][y]。

累加:f[x][y]=(f[x][y]+d[x][y][0]+d[x][y][1])%Mod

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b)  for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxN=500;

int N;
LL Mod;
int flag[maxN+100];
int cnt,ge,prime[maxN+100];
int s[maxN+100];
LL g[(1<<10)+100];
LL f[(1<<9)+10][(1<<9)+10],d[(1<<9)+10][(1<<9)+10][2];
LL ans;

#define wei(v,k) (((v)>>((k)-1))&1)
#define two(k) (1<<(k-1))

int main()
  {
      freopen("dinner.in","r",stdin);
      freopen("dinner.out","w",stdout);
      int i,j,k;
      N=gint();Mod=gll();
      re(i,2,N)
        {
            if(!flag[i])prime[++cnt]=i;
            for(j=1;j<=cnt && prime[j]*i<=N;j++)
              {
                  flag[i*prime[j]]=1;
                  if(i%prime[j]==0)break;
              }
        }
      if(cnt<=10)
        {
              re(i,2,N)re(j,1,cnt)if(i%prime[j]==0)s[i]|=two(j);
              g[0]=1;
              re(i,2,N)red(j,(1<<cnt)-1,0)g[j|s[i]]=(g[j|s[i]]+g[j])%Mod;
              ans=0;
              re(i,0,(1<<cnt)-1)re(j,0,(1<<cnt)-1)if((i&j)==0)ans=(ans+g[i]*g[j])%Mod;
              cout<<ans<<endl;
        }
      else
        {
            ge=9;
            re(i,2,N)re(j,1,ge)if(i%prime[j]==0)s[i]|=two(j);
            g[0]=1;
            re(i,2,N)
              {
                  int t=i;
                  re(j,1,ge)while(t%prime[j]==0)t/=prime[j];
                  if(t!=1)continue;
                  red(j,(1<<ge)-1,0)g[j|s[i]]=(g[j|s[i]]+g[j])%Mod;
              }
            re(i,0,(1<<ge)-1)re(j,0,(1<<ge)-1)if((i&j)==0)f[i][j]=g[i]*g[j]%Mod;
            re(k,ge+1,cnt)
              {
                  mmst(d,0);
                for(int v=prime[k];v<=N;v+=prime[k])
                  red(i,(1<<ge)-1,0)red(j,(1<<ge)-1,0)if((i&j)==0)
                    {
                        if(((i|s[v])&j)==0)d[i|s[v]][j][0]=(d[i|s[v]][j][0]+d[i][j][0]+f[i][j])%Mod;
                        if((i&(j|s[v]))==0)d[i][j|s[v]][1]=(d[i][j|s[v]][1]+d[i][j][1]+f[i][j])%Mod;
                    }
                re(i,0,(1<<ge)-1)re(j,0,(1<<ge)-1)if((i&j)==0)f[i][j]=(f[i][j]+d[i][j][0]+d[i][j][1])%Mod;
              }
            ans=0;
            re(i,0,(1<<ge)-1)re(j,0,(1<<ge)-1)if((i&j)==0)ans=(ans+f[i][j])%Mod;
            cout<<ans<<endl;
        }
      return 0;
  }
View Code

 D2T1

多叉哈夫曼树。

如果K=2,那就是裸的哈夫曼树。现在K不是2,就是多叉哈夫曼树。

根据二叉哈夫曼树的类比,我们可以得到多叉哈夫曼树的做法:将前K小的点拿出来,然后删去,再加入一个权值等于和的点。

但是有几点地方要注意,有可能最后会剩下小于K个,这样无法取,我们在一开始的时候就补若干个0,使得个数为(K-1)的倍数+1

对于第二问,我们可以可以再排序的时候设置第二关键字,先取深度小的。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<LL,LL> PLL;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b)  for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

int N,K;

struct cmp{inline bool operator ()(PLL x,PLL y){return (x.fi==y.fi)?x.se>y.se:x.fi>y.fi;}};
priority_queue<PLL,vector<PLL>,cmp>Q;
LL ans,cnt;

int main()
  {
      freopen("epic.in","r",stdin);
      freopen("epic.out","w",stdout);
      int i;
      N=gint();K=gint();
      re(i,1,N)Q.push(PLL(gll(),1));
      while((N-1)%(K-1)!=0)Q.push(PLL(0,1)),N++;
      while(Q.size()!=1)
        {
            PLL t=PLL(0,0);
            re(i,1,K){t.fi+=Q.top().fi;upmax(t.se,Q.top().se+1);Q.pop();}
            ans+=t.fi;
            Q.push(t);
        }
      cout<<ans<<endl;
      cout<<Q.top().se-1<<endl;
      return 0;
  }
View Code

D2T2

后缀数组+并查集。

这种问题好像经常遇到,至少看到过2次了,后缀数组一定要熟悉啊。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b)  for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxN=300000;
const LL INF=1LL<<62;

int N;
char S[maxN+100];
LL a[maxN+100];

int r[maxN+100],sa[maxN+100],rank[maxN+100],height[maxN+100];
int table[maxN+100],wa[maxN+100],wb[maxN+100];
inline bool cmp(int *r,int a,int b,int len){return r[a]==r[b] && r[a+len]==r[b+len];}
inline void da()
  {
        int i,j,k,p,*x=wa,*y=wb,tol;
        re(i,1,N)r[i]=S[i]-' '+1;
        p=0;re(i,1,N)upmax(p,x[i]=r[i]);
        re(i,1,p)table[i]=0;
        re(i,1,N)table[x[i]]++;
        re(i,2,p)table[i]+=table[i-1];
        red(i,N,1)sa[table[x[i]]--]=i;
        for(swap(x,y),x[sa[1]]=p=1,i=2;i<=N;i++)
          x[sa[i]]=cmp(y,sa[i-1],sa[i],0)?p:++p;
        for(j=1;p<N;j*=2)
          {
                tol=0;
                re(i,N-j+1,N)y[++tol]=i;
                re(i,1,N)if(sa[i]-j>=1)y[++tol]=sa[i]-j;
                re(i,1,p)table[i]=0;
                re(i,1,N)table[x[y[i]]]++;
                re(i,2,p)table[i]+=table[i-1];
                red(i,N,1)sa[table[x[y[i]]]--]=y[i];
                for(swap(x,y),x[sa[1]]=p=1,i=2;i<=N;i++)
                  x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p;
            }
        re(i,1,N)rank[sa[i]]=i;
        for(i=1,j,k=0;i<=N-1;height[rank[i++]]=k)
          for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
    }

LL ge,As;
LL ans1[maxN+100],ans2[maxN+100];
struct Tbak
  {
      int val,pos;
      inline Tbak(int _val=0,int _pos=0){val=_val;pos=_pos;}
    }bak[maxN+100];int cnt;
inline bool cmpbak(Tbak a,Tbak b){return a.val>b.val;}

PII route[maxN+100];
LL o[maxN+100],Q1[maxN+100],Q2[maxN+100],Q3[maxN+100],Q4[maxN+100];
/*
Q1 最大非负数
Q2 最小非负数
Q3 最大非正数 
Q4 最小非正数 
*/ 
int pa[maxN+100];
inline int findroot(int a){return pa[a]<0?a:pa[a]=findroot(pa[a]);}

int main()
  {
      freopen("savour.in","r",stdin);
      freopen("savour.out","w",stdout);
      int i;
      N=gint();
      scanf("%s
",S+1);
      re(i,1,N)a[i]=gll();
      S[++N]=' ';
      da();
      
      re(i,1,N)o[rank[i]]=a[i];
        re(i,1,N)
          {
              pa[i]=-1;
                route[i]=PII(i,i);
                if(o[i]>=0) Q1[i]=o[i]; else Q1[i]=-INF;
                if(o[i]>=0) Q2[i]=o[i]; else Q2[i]=INF;
                if(o[i]<=0) Q3[i]=o[i]; else Q3[i]=-INF;
                if(o[i]<=0) Q4[i]=o[i]; else Q4[i]=INF;
            }
        
      re(i,3,N)bak[++cnt]=Tbak(height[i],i);
      sort(bak+1,bak+cnt+1,cmpbak);
      int head=1;
      ge=0;As=-INF;
      red(i,N-2,0)
        {
            while(head<=cnt && bak[head].val==i)
              {
                  int f1=findroot(bak[head].pos-1),f2=findroot(bak[head].pos);
                  PII D1=route[f1],D2=route[f2];
                  ge+=LL(D1.se-D1.fi+1)*LL(D2.se-D2.fi+1);
                  if(Q1[f1]!=-INF && Q1[f2]!=-INF) upmax(As,Q1[f1]*Q1[f2]);
                  if(Q4[f1]!=INF && Q4[f2]!=INF) upmax(As,Q4[f1]*Q4[f2]);
                  if(Q2[f1]!=INF && Q3[f2]!=-INF) upmax(As,Q2[f1]*Q3[f2]);
                  if(Q3[f1]!=-INF && Q2[f2]!=INF) upmax(As,Q3[f1]*Q2[f2]);
                  
                  if(pa[f1]>pa[f2])swap(f1,f2);
                  pa[f1]=pa[f1]+pa[f2];
                  pa[f2]=f1;
                  route[f1]=PII(D1.fi,D2.se);
                  upmax(Q1[f1],Q1[f2]);
                  upmin(Q2[f1],Q2[f2]);
                  upmax(Q3[f1],Q3[f2]);
                  upmin(Q4[f1],Q4[f2]);
                  
                  head++;
              }
            ans1[i]=ge;
            ans2[i]=(ge==0)?0:As;
        }
      re(i,0,N-2)printf("%I64d %I64d
",ans1[i],ans2[i]);
      return 0;
  }

      
View Code
原文地址:https://www.cnblogs.com/maijing/p/4678062.html