• [bzoj4777]Switch Grass


    结论:最短路径一定是单独的一条边且在最小生成树上,可以用反证法证明。
    那么求出最小生成树,对于每一个点建立一棵权值线段树,再对每一个权值线段树上的叶子节点开一个multiset,维护所有儿子中该种颜色的权值(普通节点仍维护区间最小值),答案也需要用multiset维护。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200005
     4 #define mid (l+r>>1)
     5 multiset<int>ans,s[N*3];
     6 struct ji{
     7     int nex,to,len;
     8 }edge[N<<1];
     9 struct ji2{
    10     int x,y,z;
    11     bool operator < (const ji2 &k)const{
    12         return z<k.z;
    13     }
    14 }a[N];
    15 int E,V,V2,n,m,q,head[N],f[N],r[N],sh[N],id[N*29],ls[N*29],rs[N*29],tr[N*29],c[N];
    16 int find(int k){
    17     if (k==f[k])return k;
    18     return f[k]=find(f[k]);
    19 }
    20 void add(int x,int y,int z){
    21     edge[E].nex=head[x];
    22     edge[E].to=y;
    23     edge[E].len=z;
    24     head[x]=E++;
    25 }
    26 void update(int &k,int l,int r,int x,int y,int p,int c){
    27     if ((!k)&&(y==-1))return;
    28     if (!k)k=++V;
    29     if (l==r){
    30         if (!id[k])id[k]=++V2;
    31         if (y!=-1)
    32             if (p==1)s[id[k]].insert(y);
    33             else s[id[k]].erase(s[id[k]].find(y));
    34         if ((c==x)||(!s[id[k]].size()))tr[k]=0x3f3f3f3f;
    35         else tr[k]=(*s[id[k]].begin());
    36         return;
    37     }
    38     if (x<=mid)update(ls[k],l,mid,x,y,p,c);
    39     else update(rs[k],mid+1,r,x,y,p,c);
    40     tr[k]=min(tr[ls[k]],tr[rs[k]]);
    41 }
    42 void dfs(int k,int fa){
    43     f[k]=fa;
    44     for(int i=head[k];i!=-1;i=edge[i].nex)
    45         if (edge[i].to!=fa){
    46             dfs(edge[i].to,k);
    47             sh[edge[i].to]=edge[i].len;
    48             update(r[k],1,n,c[edge[i].to],edge[i].len,1,c[k]);
    49         }
    50     ans.insert(tr[r[k]]);
    51 }
    52 int main(){
    53     scanf("%d%d%*d%d",&n,&m,&q);
    54     memset(head,-1,sizeof(head));
    55     tr[0]=0x3f3f3f3f;
    56     for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    57     sort(a+1,a+m+1);
    58     for(int i=1;i<=n;i++)f[i]=i;
    59     for(int i=1;i<=m;i++)
    60         if (find(a[i].x)!=find(a[i].y)){
    61             f[find(a[i].x)]=find(a[i].y);
    62             add(a[i].x,a[i].y,a[i].z);
    63             add(a[i].y,a[i].x,a[i].z);
    64         }
    65     for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    66     dfs(1,0);
    67     int x,y;
    68     for(int i=1;i<=q;i++){
    69         scanf("%d%d",&x,&y);
    70         if (f[x]){
    71             ans.erase(ans.find(tr[r[f[x]]]));
    72             update(r[f[x]],1,n,c[x],sh[x],-1,c[f[x]]);
    73             update(r[f[x]],1,n,y,sh[x],1,c[f[x]]);
    74             ans.insert(tr[r[f[x]]]);
    75         }
    76         ans.erase(ans.find(tr[r[x]]));
    77         update(r[x],1,n,c[x],-1,1,y);
    78         c[x]=y;
    79         update(r[x],1,n,c[x],-1,1,c[x]);
    80         ans.insert(tr[r[x]]);
    81         printf("%d\n",(*ans.begin()));
    82     }
    83 }
    View Code
  • 相关阅读:
    java实现孪生素数
    java实现孪生素数
    java实现孪生素数
    java实现孪生素数
    java实现孪生素数
    java实现连续数的公倍数
    java实现连续数的公倍数
    mysql千万级数据量根据索引优化查询速度
    MySQL特异功能之:Impossible WHERE noticed after reading const tables
    MySQL:浅析 Impossible WHERE noticed after reading const tables
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11266526.html
Copyright © 2020-2023  润新知