传送门

题意

给出一张n个点m条边的无向图,点的颜色为0/1,每次有两种操作:

1.Asksum x y,查询两点颜色为x和y的边的权值之和

2.Change x,将x颜色取反

分析

最直接的做法是每次改变点的颜色豆浆与该点所连的边更新,\(O(q*m)\),超时

那么我们考虑将点根据度数分类,将度数\(<sqrt(m)\)的点称为普通点,否则为超级点。设置sum[i][0/1]代表第i个点(超级点)与颜色为0/1相连的边的权值和。普通点颜色改变,暴力修改与普通点相连的所有的点对答案的贡献\(O(\sqrt{m})\);超级点颜色改变,直接修改对答案的贡献\(O(1)\);最后修改与变颜色的点相连的所有超级点的sum,具体细节见代码

trick

1.用vector写会wa,不知道为什么

2.一些写的更详细的blog,对于答案的贡献修改有清晰的介绍

hdu4467 Graph(构造法求解)

hdu4467 Graph(图的分块)

代码

  1. //vector(wa)
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <vector>
  6. using namespace std;
  7. #define F(i,a,b) for(int i=a;i<=b;++i)
  8. #define R(i,a,b) for(int i=a;i<b;++i)
  9. #define ll long long
  10. #define mem(a,b) memset(a,b,sizeof(a))
  11. const int N = 100100;
  12. int n,m,q,cas;
  13. int color[N],du[N],super[N];
  14. ll sum[N][2],ans[3];
  15. struct edge
  16. {
  17. int u,v;
  18. ll w;
  19. bool operator<(const edge &p)const
  20. {
  21. return u==p.u?v<p.v:u<p.u;
  22. }
  23. }e[N];
  24. struct node
  25. {
  26. int v;
  27. ll w;
  28. node(int _v,ll _w):v(_v),w(_w){}
  29. };
  30. vector<node>ve[N];
  31. void change(int x)
  32. {
  33. color[x]^=1;
  34. if(super[x])
  35. {
  36. ans[(color[x]^1)+0]-=sum[x][0];
  37. ans[(color[x]^1)+1]-=sum[x][1];
  38. ans[(color[x])+0]+=sum[x][0];
  39. ans[(color[x])+1]+=sum[x][1];
  40. }
  41. else
  42. {
  43. for(int i=0;i<ve[x].size();++i)
  44. {
  45. int y=ve[x][i].v;ll z=ve[x][i].w;
  46. ans[(color[x]^1)+color[y]]-=z;
  47. ans[(color[x])+color[y]]+=z;
  48. }
  49. }
  50. for(int i=0;i<ve[x].size();++i)
  51. {
  52. int y=ve[x][i].v;ll z=ve[x][i].w;
  53. if(super[y])
  54. {
  55. sum[y][color[x]^1]-=z;
  56. sum[y][color[x]]+=z;
  57. }
  58. }
  59. }
  60. /*
  61. void check()
  62. {
  63. for(int i=1;i<=n;++i) printf("%d%c",color[i],i==n?'\n':' ');
  64. for(int i=1;i<=n;++i) printf("%lld %lld%c",sum[i][0],sum[i][1],i==n?'\n':' ');
  65. }
  66. */
  67. int main()
  68. {
  69. while(scanf("%d %d",&n,&m)!=EOF)
  70. {
  71. mem(du,0);mem(ans,0);mem(sum,0);
  72. F(i,0,n) ve[i].clear();
  73. F(i,1,n) scanf("%d",color+i);
  74. F(i,1,m) {scanf("%d %d %lld",&e[i].u,&e[i].v,&e[i].w);if(e[i].u>e[i].v) swap(e[i].u,e[i].v);}
  75. sort(e+1,e+1+m);
  76. int cnt=0;
  77. for(int i=1,j;i<=m;i=j){
  78. for(j=i+1;j<=m;++j) if(e[i].u==e[j].u&&e[i].v==e[j].v) e[i].w+=e[j].w;else break;
  79. e[++cnt]=e[i];
  80. }
  81. F(i,1,cnt) du[e[i].u]++,du[e[i].v]++;
  82. int judge=sqrt(cnt);
  83. F(i,1,n) super[i]=(du[i]>=judge);
  84. F(i,1,cnt)
  85. {
  86. if(super[e[i].u]) {ve[e[i].v].push_back(node(e[i].u,e[i].w));sum[e[i].u][color[e[i].v]]+=e[i].w;}else ve[e[i].u].push_back(node(e[i].v,e[i].w));
  87. if(super[e[i].v]) {ve[e[i].u].push_back(node(e[i].v,e[i].w));sum[e[i].v][color[e[i].u]]+=e[i].w;}else ve[e[i].v].push_back(node(e[i].u,e[i].w));
  88. ans[color[e[i].u]+color[e[i].v]]+=e[i].w;
  89. }
  90. printf("Case %d:\n", ++cas);
  91. for(scanf("%d",&q);q--;)
  92. {
  93. char s[10];scanf("%s",s);
  94. if(s[0]=='A'){ int x,y;scanf("%d %d",&x,&y);printf("%lld\n",ans[x+y]); }
  95. else
  96. {
  97. int x;scanf("%d",&x);change(x);
  98. }
  99. }
  100. // check();
  101. }
  102. return 0;
  103. }
  1. //邻接表(ac)
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <vector>
  7. using namespace std;
  8. #define F(i,a,b) for(int i=a;i<=b;++i)
  9. #define ll long long
  10. #define mem(a,b) memset(a,b,sizeof(a))
  11. const int N = 100100;
  12. int n,m,q,cas;
  13. int color[N],du[N],super[N];
  14. ll sum[N][2],ans[3];
  15. struct edge
  16. {
  17. int u,v;
  18. ll w;
  19. edge(int u=0,int v=0,ll w=0):u(u),v(v),w(w){}
  20. bool operator<(const edge &p)const
  21. {
  22. return u==p.u?v<p.v:u<p.u;
  23. }
  24. }e[N];
  25. int head[N][2], v[N<<2], nxt[N<<2], tot;
  26. ll w[N<<2];
  27. inline void add(int t, int _u, int _v, ll _w){ v[++tot] = _v; w[tot] = _w; nxt[tot] = head[_u][t]; head[_u][t] = tot; }
  28. int main()
  29. {
  30. while(scanf("%d %d",&n,&m)!=EOF)
  31. {
  32. mem(du,0);
  33. F(i,1,n) scanf("%d",color+i);
  34. F(i,1,m) {scanf("%d %d %I64d",&e[i].u,&e[i].v,&e[i].w);if(e[i].u>e[i].v) swap(e[i].u,e[i].v);}
  35. sort(e+1,e+m+1);
  36. //对边去重
  37. int cnt=0;
  38. for(int i=1,j;i<=m;i=j){
  39. for(j=i+1;j<=m&&e[i].u==e[j].u&&e[i].v==e[j].v;++j)e[i].w+=e[j].w;
  40. e[++cnt]=e[i];
  41. }
  42. F(i,1,cnt) du[e[i].u]++,du[e[i].v]++;//计算度数
  43. int judge=sqrt(cnt);//设定界限,高于界限为超级点,否则为普通点
  44. F(i,1,n) super[i]=(du[i]>=judge);
  45. mem(head,0);tot=0;mem(ans,0);mem(sum,0);
  46. F(i,1,cnt)//构建邻接表
  47. {
  48. int x=e[i].u,y=e[i].v;ll z=e[i].w;
  49. //如果为超级点,就要放到被访问的位置,否则放到访问的位置,对超级点相连的边记录sum值
  50. if(super[x]) {add(1,y,x,z);sum[x][color[y]]+=z;}else add(0,x,y,z);
  51. if(super[y]) {add(1,x,y,z);sum[y][color[x]]+=z;}else add(0,y,x,z);
  52. ans[color[x]+color[y]]+=z;//将边权记录到答案中
  53. }
  54. printf("Case %d:\n", ++cas);
  55. for(scanf("%d",&q);q--;)
  56. {
  57. char s[10];scanf("%s",s);
  58. if(s[0]=='A'){ int x,y;scanf("%d %d",&x,&y);printf("%I64d\n",ans[x+y]); }
  59. else
  60. {
  61. int x;scanf("%d",&x);
  62. color[x]^=1;//先取反
  63. if(super[x])
  64. {
  65. for(int i = 0; i < 2; i++)//点的状态改变,将答案中的与点有关的部分转移
  66. {
  67. ans[(color[x] ^ 1) + i] -= sum[x][i];
  68. ans[color[x] + i] += sum[x][i];
  69. }
  70. }
  71. else
  72. {
  73. for(int i=head[x][0];i;i=nxt[i])//普通点暴力更新答案
  74. {
  75. ans[(color[x]^1)+color[v[i]]]-=w[i];
  76. ans[color[x]+color[v[i]]]+=w[i];
  77. }
  78. }
  79. for(int i=head[x][1];i;i=nxt[i])//暴力修改与点相连的超级点sum
  80. {
  81. sum[v[i]][color[x]^1]-=w[i];
  82. sum[v[i]][color[x]]+=w[i];
  83. }
  84. }
  85. }
  86. }
  87. return 0;
  88. }

HDU4467:Graph(点的度数分块)的更多相关文章

  1. HDU4467 Graph【轻重点维护】

    HDU4467 Graph 题意: 给出一张染色图,\(n\)个点每个点是黑色或者白色,\(m\)条带权边,\(q\)次操作,有两种操作: 改变一个点的颜色 问所有边中两个端点的颜色为给定情况的边权和 ...

  2. hdu4467 Graph

    Graph Problem Description P. T. Tigris is a student currently studying graph theory. One day, when h ...

  3. 2019牛客多校三 A. Graph Games (图分块)

    大意: 给定无向图, 定义$S(x)$为$x$的邻接点集合. 每次操作翻转$[L,R]$范围的边, 询问$S(x)$与$S(y)$是否相等. 快速判断集合相等可以用$CF 799F$的技巧. 采用$h ...

  4. HihoCoder 1629 Graph (2017 ACM-ICPC 北京区域赛 C题,回滚莫队 + 启发式合并 + 可撤销并查集)

    题目链接  2017 ACM-ICPC Beijing Regional Contest Problem C 题意  给定一个$n$个点$m$条边的无向图.现在有$q$个询问,每次询问格式为$[l, ...

  5. Comet OJ - Contest #5 迫真图论 (图分块)

    大意: 给定无向图, 点$i$点权$b_i$, 边$(x,y,z)$对序列贡献是把$A[b_x \oplus b_y]$加上$z$. 多组询问, 一共三种操作: 1. 修改点权. 2.修改边权. 3. ...

  6. 2019牛客多校第三场A Graph Games 分块思想

    题意:给你一张无向图,设s(x)为与x直接相连的点的集合,题目中有两种操作: 1:1 l r 将读入的边的序列中第l个到第r个翻转状态(有这条边 -> 没这条边, 没这条边 -> 有这条边 ...

  7. Codeforces 506D Mr. Kitayuta's Colorful Graph(分块 + 并查集)

    题目链接  Mr. Kitayuta's Colorful Graph 把每种颜色分开来考虑. 所有的颜色分为两种:涉及的点的个数 $> \sqrt{n}$    涉及的点的个数 $<= ...

  8. 2019牛客暑期多校训练营(第三场)A.Graph Games (分块)

    题意:给你n个点 m条边的一张图 现在有q次操作 每次操作可以选择反转l~r的边号 也可以询问S(l)和S(r) 连接成的点集是否相同 思路:我们把m条边分块 用一个S数组维护每块对一个点的贡献 然后 ...

  9. HDU 4467 分块

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4467 题意:给定n个点m条边的无向图,点被染色(黑0/白1),边带边权.然后q个询问.询问分为两种: ...

随机推荐

  1. 转:一个android开发者独立开发社交app全过程

    http://www.cnblogs.com/linguanh/p/5683069.html

  2. HDOJ 1217 Arbitrage(拟最短路,floyd算法)

    Arbitrage Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  3. html5 式程序员表白

    html5 式程序员表白 王海庆 于 星期三, 04/06/2014 - 00:44 提交 今天是个好日子,2014年5月20日,表白的最佳时机,虽说孩子已经四岁.结婚已经五年.可是也不能够偷懒.于是 ...

  4. 菜鸟系列之C/C++经典试题(三)

    设计包括min函数的栈 题目:定义栈的数据结构,要求加入一个min函数,可以得到栈的最小元素.要求函数min.push以及pop的时间复杂度都是O(1). 分析:这是2006年google的一道面试题 ...

  5. 基于bootstrap_登陆页面

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. Matlab依据样本随机数求概率曲线

    相关Matlab函数:hist, bar, cdfplot, ksdensity (1) hist函数 n = hist(Y, x)  假设x是一个向量,返回x的长度个以x为中心的,Y的分布情况. 比 ...

  7. Nova虚拟机启动提示libvirtError

    OpenStack自动化安装基本折腾完毕,装一次大概也就10分钟,但是装完后今天我的虚拟机起不来,经过查找log发 现如下图提示: 已经到这里,说明已经过了nova-sheduler那一关,跟踪一下代 ...

  8. Ajax的简单实现(Json)

    之前写的是一般的Ajax if (request.status === 200) { document.getElementById("createResult").innerHT ...

  9. SpringMVC -- 第一个简单的程序

    学习springMVC,我们来记录下第一个HelloWord的程序 首先.我们组织须要的jar包 commons-logging-1.1.3.jar spring-aop-4.1.7.RELEASE. ...

  10. HBase数据压缩编码探索

    摘要: 本文主要介绍了hbase对数据压缩,编码的支持,以及云hbase在社区基础上对数据压缩率和访问速度上了进行的改进. 前言 你可曾遇到这种需求,只有几百qps的冷数据缓存,却因为存储水位要浪费几 ...