zoukankan      html  css  js  c++  java
  • HDU

    n个点,m条无向边边有权值,(1 ≤ n,m ≤ 10 5) 。每个点不是黑色就是白色,以0或1区分。

    有q组操作(1 ≤ q ≤ 10 5),分为两种:一种是将i号点的颜色改变,一种是给出两个颜色(可以相同),询问图中所有两端是这两种颜色的边的权值之和。

    暴力的想法很好想,我们用ans[0] ans[1] ans[2] 分别记录 同黑 、 异色 、同白 的答案,每次改i号点颜色时就遍历所有与i号点相邻的点,以之修改 三个ans ,但这一看就会TLE。

    还是用点分块,分轻重点,(见HDU - 4858 项目管理 ) ,i号点是重点,则sum[0][i]维护其到相邻的黑色点的和,sum[1][i]维护白色。

    改变颜色时修改ans,轻点爆搜修改,重点根据sum[][i]修改答案。但无论轻重点,都要修改其指向的重点的sum[][i]。

    ps : 这题需要把预处理等价的边全部合并,否则还是会TLE。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define fst first
      4 #define scd second
      5 #define pb(x) push_back((x))
      6 #define mkp(x,y) make_pair((x),(y)) 
      7 #define ist(x) insert((x))
      8 typedef long long ll;
      9 typedef pair<int ,int > pii;
     10 typedef pair<ll ,ll > pll;
     11 typedef vector< int > vi;
     12 ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
     13 ll qPow(ll a,ll b,ll mod){ ll ret=1ll;while(b){ if(b&1) ret=ret*a%mod;a=a*a%mod;b>>=1;} return ret; }
     14 
     15 const int maxn=1e5+5;
     16 
     17 struct Edge{
     18     int to;
     19     ll weight;
     20     Edge(int v,ll w):to(v),weight(w) {}
     21 };
     22 
     23 struct Bian{
     24     int u;
     25     int v;
     26     ll wei;
     27     Bian(int a,int b,ll c):u(a),v(b),wei(c) {}
     28     Bian(){};
     29 };
     30 ll ans[3];
     31 int degree[maxn];
     32 ll sum[2][maxn];
     33 int col[maxn];
     34 vector< Edge > G[maxn];
     35 Bian bin[maxn];
     36 Bian raw[maxn];
     37 bool heavy[maxn];
     38 int bound;
     39 
     40 void addedge(int u,int v,ll w){
     41     if(!heavy[u]) G[u].pb(Edge(v,w));
     42     else if(heavy[v]) G[u].pb(Edge(v,w)); 
     43 } 
     44 
     45 bool cmp(Bian a,Bian b){
     46     if(a.u!=b.u) return a.u<b.u;
     47     return a.v<b.v;
     48 }
     49 
     50 int main(){
     51     //freopen("data.in","r",stdin);
     52     //freopen("data.out","w",stdout);
     53     int N,M;
     54     int cntcase=1;
     55     while(~scanf("%d%d",&N,&M)){
     56         for(int i=1;i<=N;++i)  scanf("%d",&col[i]);
     57         for(int i=1;i<=N;++i){
     58             degree[i]=0;
     59             sum[0][i]=0ll;sum[1][i]=0ll;
     60             G[i].clear();
     61             heavy[i]=false;
     62         }
     63         ans[0]=ans[1]=ans[2]=0ll;
     64         for(int i=1;i<=M;++i){
     65             int u,v;
     66             ll w;scanf("%d%d%lld",&u,&v,&w);
     67             if(u>v) swap(u,v);
     68             Bian tmp=Bian(u,v,w);
     69             //degree[u]++,degree[v]++;
     70             raw[i] = tmp;
     71         }
     72         sort(raw+1,raw+1+M,cmp);
     73         //for(int i=1;i<=M;++i) printf("%d - %d : %lld
    ",raw[i].u,raw[i].v,raw[i].wei);
     74         int cntedge=0;
     75         for(int i=1,j=2;i<=M;i=j){
     76             for(j=i+1;j<=M;++j){
     77                 if(raw[i].u==raw[j].u&&raw[i].v==raw[j].v)
     78                 {
     79                     raw[i].wei+=raw[j].wei;
     80                 }
     81                 else break;    
     82             }
     83             bin[++cntedge]=raw[i];
     84         }
     85         int bound=sqrt(cntedge);
     86         for(int i=1;i<=cntedge;++i){
     87             //printf("%d - %d : %lld
    ",bin[i].u,bin[i].v,bin[i].wei);
     88             degree[bin[i].u]++;
     89             degree[bin[i].v]++;
     90         }
     91         for(int i=1;i<=N;++i) if(degree[i]>bound) heavy[i]=true;
     92         for(int i=1;i<=cntedge;++i){
     93             int u,v;
     94             u=bin[i].u,v=bin[i].v;
     95             ll w;
     96             w=bin[i].wei;
     97             addedge(u,v,w);
     98             addedge(v,u,w);
     99             ans[col[u]+col[v]]+=w;
    100             if(heavy[v]){
    101                 sum[col[u]][v]+=w; 
    102             }
    103             if(heavy[u]){
    104                 sum[col[v]][u]+=w;
    105             }
    106         }
    107         /*
    108         for(int i=0;i<3;++i) printf("ans [%d]: %lld
    ",i,ans[i]);
    109         for(int i=0;i<2;++i){
    110             for(int j=1;j<=N;++j){
    111                 printf("sum [%d][%d] : %lld
    ",i,j,sum[i][j]);
    112             }
    113         } 
    114         */
    115         printf("Case %d:
    ",cntcase++);
    116         int Q;scanf("%d",&Q);
    117         for(int i=0;i<Q;++i){
    118             char op[10];scanf("%s",op);
    119             if(op[0]=='A'){
    120                 int aa,bb;scanf("%d%d",&aa,&bb) ;
    121                 printf("%I64d
    ",ans[aa+bb]);
    122             }
    123             else{
    124                 int u;scanf("%d",&u);
    125                 if(!heavy[u]){
    126                     for(auto e : G[u]){
    127                         int to=e.to;
    128                         ll wei=e.weight;
    129                         //printf("light %d -> %d : %d
    ",u,to,wei);
    130                         if(heavy[to]){
    131                             sum[col[u]][to]-=wei;
    132                             sum[(col[u]^1)][to]+=wei;
    133                         }                         
    134                         ans[col[u]+col[to]]-=wei;
    135                         ans[(col[u]^1)+col[to]]+=wei;
    136                         //for(int i=0;i<3;++i) printf("ans [%d]: %lld
    ",i,ans[i]);
    137                     }
    138                     col[u]^=1;
    139                 }
    140                 else{
    141                     ans[col[u]+0]-=sum[0][u];
    142                     ans[col[u]+1]-=sum[1][u];
    143                     ans[(col[u]^1)+0]+=sum[0][u];
    144                     ans[(col[u]^1)+1]+=sum[1][u];
    145                     //for(int i=0;i<3;++i) printf("ans [%d]: %lld
    ",i,ans[i]);
    146                     for(auto e : G[u]){
    147                         int to=e.to;
    148                         ll wei=e.weight;
    149                         //printf("heavy : %d -> %d : %d
    ",u,to,wei);
    150                         sum[col[u]][to]-=wei;
    151                         sum[(col[u]^1)][to]+=wei;
    152                     }
    153                     col[u]^=1;
    154                 }
    155                 //for(int i=1;i<=N;++i)  printf(" %d ",col[i]);
    156                 //puts("");
    157                 //for(int i=0;i<3;++i) printf("ans [%d]: %lld
    ",i,ans[i]);
    158             }
    159         }
    160     }
    161     return 0;
    162 }
    View Code

    等一下,既然重点也要搜,为何不“一视同仁”。无论轻重,都用sum[][i]修改,然后搜索修改其指向的点的sum[][i]。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define fst first
      4 #define scd second
      5 #define pb(x) push_back((x))
      6 #define mkp(x,y) make_pair((x),(y)) 
      7 #define ist(x) insert((x))
      8 typedef long long ll;
      9 typedef pair<int ,int > pii;
     10 typedef pair<ll ,ll > pll;
     11 typedef vector< int > vi;
     12 ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
     13 ll qPow(ll a,ll b,ll mod){ ll ret=1ll;while(b){ if(b&1) ret=ret*a%mod;a=a*a%mod;b>>=1;} return ret; }
     14 
     15 const int maxn=1e5+5;
     16 
     17 struct Edge{
     18     int to;
     19     ll weight;
     20     Edge(int v,ll w):to(v),weight(w) {}
     21 };
     22 
     23 struct Bian{
     24     int u;
     25     int v;
     26     ll wei;
     27     Bian(int a,int b,ll c):u(a),v(b),wei(c) {}
     28     Bian(){};
     29 };
     30 ll ans[3];
     31 int degree[maxn];
     32 ll sum[2][maxn];
     33 int col[maxn];
     34 vector< Edge > G[maxn];
     35 Bian bin[maxn];
     36 Bian raw[maxn];
     37 bool heavy[maxn];
     38 int bound;
     39 
     40 void addedge(int u,int v,ll w){
     41     if(!heavy[u]) G[u].pb(Edge(v,w));
     42     else if(heavy[v]) G[u].pb(Edge(v,w)); 
     43 } 
     44 
     45 bool cmp(Bian a,Bian b){
     46     if(a.u!=b.u) return a.u<b.u;
     47     return a.v<b.v;
     48 }
     49 
     50 int main(){
     51     //freopen("data.in","r",stdin);
     52     //freopen("data.out","w",stdout);
     53     int N,M;
     54     int cntcase=1;
     55     while(~scanf("%d%d",&N,&M)){
     56         for(int i=1;i<=N;++i)  scanf("%d",&col[i]);
     57         for(int i=1;i<=N;++i){
     58             degree[i]=0;
     59             sum[0][i]=0ll;sum[1][i]=0ll;
     60             G[i].clear();
     61             heavy[i]=false;
     62         }
     63         ans[0]=ans[1]=ans[2]=0ll;
     64         for(int i=1;i<=M;++i){
     65             int u,v;
     66             ll w;scanf("%d%d%lld",&u,&v,&w);
     67             if(u>v) swap(u,v);
     68             Bian tmp=Bian(u,v,w);
     69             //degree[u]++,degree[v]++;
     70             raw[i] = tmp;
     71         }
     72         sort(raw+1,raw+1+M,cmp);
     73         //for(int i=1;i<=M;++i) printf("%d - %d : %lld
    ",raw[i].u,raw[i].v,raw[i].wei);
     74         int cntedge=0;
     75         for(int i=1,j=2;i<=M;i=j){
     76             for(j=i+1;j<=M;++j){
     77                 if(raw[i].u==raw[j].u&&raw[i].v==raw[j].v)
     78                 {
     79                     raw[i].wei+=raw[j].wei;
     80                 }
     81                 else break;    
     82             }
     83             bin[++cntedge]=raw[i];
     84         }
     85         int bound=sqrt(cntedge);
     86         for(int i=1;i<=cntedge;++i){
     87             //printf("%d - %d : %lld
    ",bin[i].u,bin[i].v,bin[i].wei);
     88             degree[bin[i].u]++;
     89             degree[bin[i].v]++;
     90         }
     91         for(int i=1;i<=N;++i) if(degree[i]>bound) heavy[i]=true;
     92         for(int i=1;i<=cntedge;++i){
     93             int u,v;
     94             u=bin[i].u,v=bin[i].v;
     95             ll w;
     96             w=bin[i].wei;
     97             addedge(u,v,w);
     98             addedge(v,u,w);
     99             ans[col[u]+col[v]]+=w;
    100                 sum[col[u]][v]+=w; 
    101                 sum[col[v]][u]+=w;
    102         }
    103         /*
    104         for(int i=0;i<3;++i) printf("ans [%d]: %lld
    ",i,ans[i]);
    105         for(int i=0;i<2;++i){
    106             for(int j=1;j<=N;++j){
    107                 printf("sum [%d][%d] : %lld
    ",i,j,sum[i][j]);
    108             }
    109         } 
    110         */
    111         printf("Case %d:
    ",cntcase++);
    112         int Q;scanf("%d",&Q);
    113         for(int i=0;i<Q;++i){
    114             char op[10];scanf("%s",op);
    115             if(op[0]=='A'){
    116                 int aa,bb;scanf("%d%d",&aa,&bb) ;
    117                 printf("%I64d
    ",ans[aa+bb]);
    118             }
    119             else{
    120                 int u;scanf("%d",&u);
    121                 //if(!heavy[u]){
    122                     ans[col[u]+0]-=sum[0][u];
    123                     ans[col[u]+1]-=sum[1][u];
    124                     ans[(col[u]^1)+0]+=sum[0][u];
    125                     ans[(col[u]^1)+1]+=sum[1][u];
    126                     for(auto e : G[u]){
    127                         int to=e.to;
    128                         ll wei=e.weight;
    129                         //printf("light %d -> %d : %d
    ",u,to,wei);
    130                             sum[col[u]][to]-=wei;
    131                             sum[(col[u]^1)][to]+=wei;
    132                         //for(int i=0;i<3;++i) printf("ans [%d]: %lld
    ",i,ans[i]);
    133                     }
    134                     col[u]^=1;
    135                 //}
    136                 /*
    137                 else{
    138                     ans[col[u]+0]-=sum[0][u];
    139                     ans[col[u]+1]-=sum[1][u];
    140                     ans[(col[u]^1)+0]+=sum[0][u];
    141                     ans[(col[u]^1)+1]+=sum[1][u];
    142                     //for(int i=0;i<3;++i) printf("ans [%d]: %lld
    ",i,ans[i]);
    143                     for(auto e : G[u]){
    144                         int to=e.to;
    145                         ll wei=e.weight;
    146                         //printf("heavy : %d -> %d : %d
    ",u,to,wei);
    147                         sum[col[u]][to]-=wei;
    148                         sum[(col[u]^1)][to]+=wei;
    149                     }
    150                     col[u]^=1;
    151                 }
    152                 */
    153                 //for(int i=1;i<=N;++i)  printf(" %d ",col[i]);
    154                 //puts("");
    155                 //for(int i=0;i<3;++i) printf("ans [%d]: %lld
    ",i,ans[i]);
    156             }
    157         }
    158     }
    159     return 0;
    160 }
    View Code

    想象一下轻重点的连接关系,分块实在是厉害。


    2018.08.13

    "一视同仁" 其实还是搞错的,像下面这组数据,先改 重点 再改轻点,会出错。因为修改重点的影响 无法传给 轻点的sum[][i]。

    os:能AC纯属数据出的弱吧。

    5 4
    0 0 0 0 0
    1 5 1
    2 5 2
    3 5 3
    4 5 4
    11
    Asksum 0 0
    Asksum 0 1
    Asksum 1 1
    Change 5
    Asksum 0 0
    Asksum 0 1
    Asksum 1 1
    Change 1
    Asksum 0 0
    Asksum 0 1
    Asksum 1 1

    还是老老实实 轻点爆搜修改,重点用sum[][i]改吧。

    时刻谨记 : 轻点影响轻重点 ,重点只影响重点。

  • 相关阅读:
    Linux删除tunnel的方法
    rpm 强制更新安装
    普通用户使用kubectl
    网络通信过程中mac地址和ip地址的必要性
    Quartz.net开源作业调度框架使用详解
    C# 开源组件--Word操作组件DocX
    用c#创建支持多语言的WinForm应用程序
    使用JavaScript获取日期加随机数生成单号
    C# winform treeView checkbox全选反选
    DevExpress控件的GridControl控件小结
  • 原文地址:https://www.cnblogs.com/Kiritsugu/p/9410930.html
Copyright © 2011-2022 走看看