• 【NOIP模拟】战争


    题面

    分析

    正难则反系列

    删除操作很难维护,倒过来,加边维护。并查集同时维护这个集合的祖先和点权和。

    合并两个集合的代价就是 sum[x]*sum[y]

    但是要注意最后不一定把所有点删完了,所以最后一次删除后的答案要dfs一下联通块特殊求

    【然而出题人并没有卡这个..】

    代码

    1. #include<bits/stdc++.h>  
    2. using namespace std;  
    3. #define N 1101000  
    4. #define ll long long   
    5. const ll mod=1e9+7;  
    6. ll n,m,k,cnt,pos;  
    7. ll fa[N],sum[N],ans[N],vis[N],mark[N],first[N];  
    8. vector<ll>v[N];  
    9. struct email  
    10. {  
    11.     ll u,v;  
    12.     ll nxt;  
    13. }e[N*4];  
    14. inline ll find(ll x){return (fa[x]==x)?x:fa[x]=find(fa[x]);}  
    15. inline void add(ll u,ll v)  
    16. {  
    17.     e[++cnt].nxt=first[u];first[u]=cnt;  
    18.     e[cnt].u=u;e[cnt].v=v;  
    19. }  
    20. template<class T>  
    21. void read(T &x)  
    22. {  
    23.     x=0;  
    24.     static char c=getchar();  
    25.     while(c<'0'||c>'9') c=getchar();  
    26.     while(c>='0'&&c<='9')  
    27.     x=x*10+c-'0',c=getchar();  
    28. }  
    29.   
    30. inline void merge(int x,int y)  
    31. {  
    32.     pos=(pos+(sum[x]*sum[y])%mod)%mod;  
    33.     fa[y]=x;sum[x]+=sum[y];sum[x]%=mod;  
    34. }  
    35.   
    36. inline void dfs(ll u)  
    37. {  
    38.   
    39.     vis[u]=1;  
    40.     for(ll i=first[u];i;i=e[i].nxt)  
    41.     {  
    42.         ll v=e[i].v;  
    43.         if(vis[v]||mark[v])continue;  
    44.         dfs(v);  
    45.         ll fax=find(u),fay=find(v);  
    46.         merge(fax,fay);  
    47.     }  
    48. }  
    49.   
    50.   
    51. int main()  
    52. {  
    53.     read(n);read(m);  
    54.     for(ll u=2;u<=n;u++)  
    55.     {  
    56.         ll v;  
    57.         read(v);  
    58.         add(u,v);add(v,u);  
    59.     }  
    60.     for(ll i=1;i<=n;i++)sum[i]=i,fa[i]=i;     
    61.     for(ll i=1;i<=m;i++)  
    62.     {  
    63.         ll p;read(k);  
    64.         for(ll j=0;j<k;j++)  
    65.             read(p),mark[p]=1,v[i].push_back(p);  
    66.     }  
    67.     for(ll i=1;i<=n;i++)  
    68.         if(mark[i]==0&&vis[i]==0)  
    69.             dfs(i);  
    70.     ans[m+1]=pos;  
    71.     for(ll x=m;x>=1;x--)  
    72.     {  
    73.         for(ll j=0;j<v[x].size();j++)  
    74.         {  
    75.             ll u=v[x][j];  
    76.             ll fax=find(u);  
    77.             for(int i=first[u];i;i=e[i].nxt)  
    78.             {  
    79.                 int v=e[i].v;  
    80.                 if(mark[v])continue;  
    81.                 ll fay=find(v);  
    82.                 merge(fax,fay);  
    83.             }  
    84.             mark[u]=0;  
    85.         }  
    86.         ans[x]=pos;  
    87.     }  
    88.     for(ll i=1;i<=m+1;i++)  
    89.     printf("%lld ",ans[i]);  
    90. }  
  • 相关阅读:
    HDU 1162 Eddy's picture (最小生成树)(java版)
    codeforces 735D Taxes(数论)
    codeforces 735C Tennis Championship(贪心+递推)
    codeforces 2B The least round way(DP+数学)
    codeforces 2A Winner (好好学习英语)
    codeforces 632C The Smallest String Concatenation
    codeforces 803D Magazine Ad(二分+贪心)
    codeforces 803C Maximal GCD(GCD数学)
    codeforces 803B Distances to Zero
    STL容器之优先队列(转)
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9837537.html
Copyright © 2020-2023  润新知