• cf860E Arkady and A Nobody-men (树剖)


    容易得出,如果我们按照深度一层一层地做,做完一层后,这层某个点的答案就是它的祖先们的子树大小(统计大小时不包括树根)

    由于我太菜了不会别的方法,虽然N是5e5的,还是只好用一个树剖(树状数组降常数)水过去了

    就是统计到某个点的时候把它的父亲到根+1

      1 #include<bits/stdc++.h>
      2 #define pa pair<int,int>
      3 #define CLR(a,x) memset(a,x,sizeof(a))
      4 using namespace std;
      5 typedef long long ll;
      6 const int maxn=5e5+10;
      7 
      8 inline ll rd(){
      9     ll x=0;char c=getchar();int neg=1;
     10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     12     return x*neg;
     13 }
     14 
     15 int dfn[maxn],id[maxn],tot,fa[maxn],dep[maxn],top[maxn],bot[maxn];
     16 ll tr[maxn],itr[maxn],ans[maxn];
     17 int eg[maxn][2],egh[maxn],ect,N,wson[maxn],siz[maxn];
     18 int bfn[maxn],qt,qh,root;
     19 
     20 inline void adeg(int a,int b){
     21     eg[++ect][0]=b,eg[ect][1]=egh[a];egh[a]=ect;
     22 }
     23 
     24 void dfs1(int x){
     25     // printf("!%d %d
    ",x,fa[x]);
     26     siz[x]=1;int mm=0;
     27     for(int i=egh[x];i;i=eg[i][1]){
     28         int b=eg[i][0];
     29         dep[b]=dep[x]+1;dfs1(b);
     30         if(mm<siz[b]) mm=siz[b],wson[x]=b;
     31         siz[x]+=siz[b];
     32     }
     33 }
     34 
     35 void dfs2(int x){
     36     dfn[x]=++tot,id[tot]=x;
     37     top[x]=(x==wson[fa[x]])?top[fa[x]]:x;
     38     if(wson[x]) dfs2(wson[x]);
     39     else bot[top[x]]=x;
     40     for(int i=egh[x];i;i=eg[i][1]){
     41         int b=eg[i][0];
     42         if(b==wson[x]) continue;
     43         dfs2(b);
     44     }
     45 }
     46 
     47 inline int lowbit(int x){return x&(-x);}
     48 inline void add(int tp,int bt,int x,int y){
     49     x-=tp;ll iy=y*x;
     50     for(;x<=bt-tp;x+=lowbit(x)) tr[x+tp]+=y,itr[x+tp]+=iy;
     51 }
     52 inline ll query(int tp,int x){
     53     ll re=0;x-=tp;int n=x;
     54     for(;x;x-=lowbit(x)) re+=(n+1)*tr[x+tp]-itr[x+tp];
     55     return re;
     56 }
     57 
     58 inline void tradd(int x){
     59     while(x){
     60         add(dfn[top[x]]-1,dfn[bot[top[x]]],dfn[top[x]],1);
     61         add(dfn[top[x]]-1,dfn[bot[top[x]]],dfn[x]+1,-1);
     62         x=fa[top[x]];
     63     }
     64 }
     65 inline ll trque(int x){
     66     ll re=0;
     67     while(x){
     68         // printf("!%d %d %d
    ",dfn[x],dfn[top[x]],dfn[bot[top[x]]]);
     69         re+=query(dfn[top[x]]-1,dfn[x]);
     70         x=fa[top[x]];
     71     }return re;
     72 }
     73 
     74 inline void bfs(){
     75     bfn[qh=qt=1]=root;
     76     while(qh<=qt){
     77         int p=bfn[qh++];
     78         for(int i=egh[p];i;i=eg[i][1]){
     79             // printf("%d %d
    ",i,eg[i][0]);
     80             bfn[++qt]=eg[i][0];
     81         }
     82     }
     83     int lst=2;
     84     for(int i=2;i<=qt;i++){
     85         for(;dep[bfn[lst]]!=dep[bfn[i]];lst++)
     86             ans[bfn[lst]]=trque(fa[bfn[lst]]);
     87         tradd(fa[bfn[i]]);
     88     }
     89     for(;lst<=qt;lst++)
     90         ans[bfn[lst]]=trque(fa[bfn[lst]]);
     91 }
     92 
     93 int main(){
     94     //freopen("","r",stdin);
     95     int i,j,k;
     96     N=rd();
     97     for(i=1;i<=N;i++){
     98         fa[i]=rd();
     99         if(fa[i]) adeg(fa[i],i);
    100         else root=i;
    101     }
    102     dep[1]=root;dfs1(root);dfs2(root);
    103     bfs();
    104     for(i=1;i<=N;i++)
    105         printf("%I64d ",ans[i]);
    106     return 0;
    107 }
  • 相关阅读:
    MySQL skip-character-set-client-handshake导致的一个字符集问题
    skip-character-set-client-handshake 与 character-set-client-handshake
    Innodb IO优化-配置优化
    MySQL InnoDB特性:两次写(Double Write)
    RDS MySQL InnoDB 锁等待和锁等待超时的处理
    充分利用CPU多核的处理能力 innodb_read_io_threads和innodb_write_io_threads
    MySQL InnoDB配置并发线程( innodb_thread_concurrency)
    innodb内部的并发线程
    innodb_flush_method理解
    测试快速关闭innodb的方法
  • 原文地址:https://www.cnblogs.com/Ressed/p/9811393.html
Copyright © 2020-2023  润新知