zoukankan      html  css  js  c++  java
  • Gym

    题面

    题意:T组数据,每次给你1e5个点的树(1为根),每个点有一权值,询问1-n每个节点的子树中,

             至少修改几个点的权值(每次都可以任意修改),才能让子树中任意2点的距离==他们权值差的绝对值

             无解输出-1

    题解:画图不难发现,如果这个节点有3个儿子,也就是不包含它连向它父亲的边,它还有多于2条边的话,一定不行

            因为子节点权值只能是这个节点+1或者-1,所以只能存在最多2个

            那我们就又发现了,只有这个子树,可以拉成一个链的时候,才有答案,

            考虑在链中的情况,如何判断修改最少的个数,使得这是个差为1的等差数列

            一个显然的做法,每个数减去i,比如1 4 3 5 6 3 7,每个数减去位置0 2 0 1 2 -3 0 

            众数是0,有3个,所以答案就是7-3==4,至少修改4个数

            我们再考虑合并的情况,可以使用启发式合并,每次让儿子数少的并向多的

            可是我们又发现,这个节点一旦是2棵子树合并过了,他这颗子树就废掉了,以后就不会再用了

            因为这个链已经使用了,而继续传回去的点是这个父节点,它又不在链的两端,所以总的复杂度O(n)

            多组数据的清空怕T,所以在使用后,马上进行了清空,代码有点冗余

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100007
      4 int n,v[N],siz[N],de[N],vis[N],T,u,w;
      5 vector<int> g[N];
      6 int now,cnt1[2][N*3],mx1[2],cnt2[2][N*3],mx2[2];
      7 int nod[2][N],tot[2],ad[N*3],mxx,ans[N];
      8 bool dfs(int x,int dep) 
      9 {
     10     vis[x]=1;
     11     siz[x]=1;
     12     de[x]=dep;
     13     bool re=1;
     14     int cnt=0;
     15     for(int i=0;i<g[x].size();i++)
     16         if(!vis[g[x][i]]) 
     17         {
     18             if(cnt != 0) 
     19             {
     20                 now^=1;
     21                 mx1[now]=mx2[now]=0;
     22                 for(int j=1;j<=tot[now];j++) 
     23                 {
     24                     int xx=nod[now][j];
     25                     cnt1[now][v[xx]-de[xx]]=0;
     26                     cnt2[now][v[xx]+de[xx]]=0;
     27                 }
     28                 tot[now]=0;
     29             }
     30             re&=dfs(g[x][i],dep+1),siz[x]+=siz[g[x][i]];
     31             cnt++;
     32         }
     33     if(!re || g[x].size()>3 || (x==1 && g[x].size()==3)) 
     34     {
     35         ans[x]=-1;
     36         return 0;
     37     }
     38     if(g[x].size()==3 || (x==1 && g[x].size()==2)) 
     39     {
     40         int tmp = 1;
     41         mxx = 0;
     42         for(int i = 1; i <= tot[now]; i++) 
     43         {
     44             int xx = nod[now][i];
     45             ad[v[xx] - tmp]++; mxx = max(mxx, ad[v[xx] - tmp]); tmp++;
     46         }
     47         ad[v[x] - tmp]++; mxx = max(mxx, ad[v[x] - tmp]); tmp++;
     48         for(int i = tot[now ^ 1]; i >= 1; i--) 
     49         {
     50             int xx = nod[now ^ 1][i];
     51             ad[v[xx] - tmp]++; mxx = max(mxx, ad[v[xx] - tmp]); tmp++;
     52         }
     53         ans[x] = siz[x] - mxx;
     54         
     55         tmp = 1;
     56         for(int i = 1; i <= tot[now]; i++) 
     57         {
     58             int xx = nod[now][i];
     59             ad[v[xx] - tmp]--; tmp++;
     60         }
     61         ad[v[x] - tmp]--; tmp++;
     62         for(int i = tot[now ^ 1]; i >= 1; i--) 
     63         {
     64             int xx = nod[now ^ 1][i];
     65             ad[v[xx] - tmp]--; tmp++;
     66         }
     67         
     68         tmp = 1;
     69         mxx = 0;
     70         for(int i = 1; i <= tot[now]; i++) 
     71         {
     72             int xx = nod[now][i];
     73             ad[v[xx] + tmp]++; mxx = max(mxx, ad[v[xx] + tmp]); tmp++;
     74         }
     75         ad[v[x] + tmp]++; mxx = max(mxx, ad[v[x] + tmp]); tmp++;
     76         for(int i = tot[now ^ 1]; i >= 1; i--) 
     77         {
     78             int xx = nod[now ^ 1][i];
     79             ad[v[xx] + tmp]++; mxx = max(mxx, ad[v[xx] + tmp]); tmp++;
     80         }
     81         ans[x] = min(ans[x], siz[x] - mxx);
     82         tmp = 1;
     83         for(int i = 1; i <= tot[now]; i++) 
     84         {
     85             int xx = nod[now][i];
     86             ad[v[xx] + tmp]--; tmp++;
     87         }
     88         ad[v[x] + tmp]--; tmp++;
     89         for(int i = tot[now ^ 1]; i >= 1; i--) 
     90         {
     91             int xx=nod[now^1][i];
     92             ad[v[xx]+tmp]--;tmp++;
     93         }
     94         return 0;
     95     }
     96     nod[now][++tot[now]]=x;
     97     cnt1[now][v[x]-dep]++;
     98     if(cnt1[now][v[x]-dep]>mx1[now]) mx1[now]=cnt1[now][v[x]-dep];
     99     cnt2[now][v[x]+dep]++;
    100     if(cnt2[now][v[x]+dep]>mx2[now]) mx2[now]=cnt2[now][v[x]+dep];
    101     ans[x]=siz[x]-max(mx1[now], mx2[now]);
    102     return 1;
    103 }
    104 int main() 
    105 {
    106     scanf("%d",&T);
    107     while(T--) 
    108     {
    109         scanf("%d",&n);
    110         now=0;
    111         mx1[now]=mx2[now]=0;
    112         for(int j=1;j<=tot[now];j++) 
    113         {
    114             int xx=nod[now][j];
    115             cnt1[now][v[xx]-de[xx]]=0;
    116             cnt2[now][v[xx]+de[xx]]=0;
    117         }
    118         tot[now]=0;
    119         now=1;
    120         mx1[now]=mx2[now]=0;
    121         for(int j=1;j<=tot[now];j++) 
    122         {
    123             int xx=nod[now][j];
    124             cnt1[now][v[xx]-de[xx]]=0;
    125             cnt2[now][v[xx]+de[xx]]=0;
    126         }
    127         tot[now] = 0;
    128         now = 0;
    129         for(int i=1;i<=n;i++) vis[i]=0,ans[i]=0;
    130         for(int i=1;i<=n;i++) g[i].clear();
    131         for(int i=1;i<=n;i++) scanf("%d",&v[i]),v[i]+=100000;
    132         for(int i=1;i<n;i++) 
    133         {
    134             scanf("%d%d",&u,&w);
    135             g[u].push_back(w);
    136             g[w].push_back(u);
    137         }
    138         dfs(1,1);
    139         for(int i = 1; i <= n; i++) printf("%d ", ans[i]);
    140         puts("");
    141     }
    142 }

          不挤在一次dfs里好像就短多了

      1 #include<bits/stdc++.h>
      2 #define lld long long 
      3 #define N 300007
      4 using namespace std;
      5 int T,n,nn,pn,u,w;
      6 int v[N],dep[N],fa[N],dp[N],dq[N];
      7 int ch[N],ok[N],p[N],ans[N],sz[N];
      8 vector<int> g[N];
      9 void DFS(int x)
     10 {
     11     for (auto e: g[x]) if (e!=fa[x]) DFS(e);
     12     p[pn++]=x;
     13 }
     14 void work(int id)
     15 {
     16     int t;
     17     for (int i=0;i<pn;i++)
     18     {
     19         if (id==-1) t=p[i];else t=id;
     20         ans[t]=max(ans[t],++dq[v[p[i]]+i]);
     21         ans[t]=max(ans[t],++dp[v[p[i]]-i]);
     22         if (i && id==-1) ans[p[i]]=max(ans[p[i]],ans[p[i-1]]);
     23     }
     24     for (int i=0;i<pn;i++)
     25     {
     26         dp[v[p[i]]-i]--;
     27         dq[v[p[i]]+i]--;
     28     }
     29 }
     30 void solve(int x)
     31 {
     32      pn=0;
     33      DFS(x);
     34      work(-1);
     35 }
     36 void solve2(int x)
     37 {
     38     pn=0;
     39     int tn=-1;
     40     for (auto e: g[x]) if (e!=fa[x])
     41     {
     42         DFS(e);
     43         if (tn==-1)
     44         {
     45             p[pn++]=x;
     46             tn=pn;
     47         }
     48     }
     49     reverse(p+tn,p+pn);
     50     work(x);
     51 }
     52 void dfs(int x)
     53 {
     54     ok[x]=sz[x]=1;
     55     ch[x]=0;
     56     for (auto e:g[x]) if (e!=fa[x])
     57     {
     58         ch[x]++;
     59         fa[e]=x;
     60         dfs(e);
     61         sz[x]+=sz[e];
     62         ok[x]&=ok[e];
     63     }
     64     ok[x]&=ch[x]<=1;
     65     if (!ok[x])
     66     {
     67         for (auto e:g[x]) if (e!=fa[x] && ok[e]) solve(e);
     68         if (ch[x]==2)
     69         {
     70             int c=0;
     71             for (auto e:g[x]) if (e!=fa[x] && ok[e]) c++;
     72             if (c==2) solve2(x);
     73         }
     74     }
     75 }
     76 int main()
     77 {
     78     scanf("%d",&T);
     79     while (T--) 
     80     {
     81         scanf("%d",&n);
     82         for (int i=0;i<n;i++)
     83         {
     84             g[i].clear();
     85             scanf("%d",&v[i]);
     86             v[i]+=n;
     87             ans[i]=-1;
     88         }
     89         for (int i=1;i<n;i++)
     90         {
     91             scanf("%d%d",&u,&w);
     92             u--;w--;
     93             g[u].emplace_back(w);
     94             g[w].emplace_back(u);
     95         }
     96         fa[0]=-1;
     97         dfs(0);
     98         if (ok[0]) solve(0);
     99         for (int i=0;i<n;i++) printf("%d ",ans[i]==-1?-1:sz[i]-ans[i]);
    100         puts("");
    101     }
    102 } 
  • 相关阅读:
    FTP工具类
    Mac下git用户名密码问题
    python3 可能是类似于java的方法重载
    Dos窗口默认设置修改
    登录接口,密码前端密码加密
    编码中存在的问题
    在django项目中使用selenium报错:TypeError: environment can only cantain string
    python实现:base64与图片的转换
    查看电脑支持的文字, .ttf文件
    获取指定目录下的所有文件,直到底
  • 原文地址:https://www.cnblogs.com/qywhy/p/10830166.html
Copyright © 2011-2022 走看看