HDU4467 Graph

题意:

给出一张染色图,\(n\)个点每个点是黑色或者白色,\(m\)条带权边,\(q\)次操作,有两种操作:

  1. 改变一个点的颜色
  2. 问所有边中两个端点的颜色为给定情况的边权和是多少

题解:

首先因为有重边,所以先把重边合并一下

然后按每个点的度数是否大于\(\sqrt{边总数}\),把点分轻点和重点,同时记录所有三种询问情况的答案

在图中,重点我们保存其所有连的重点的边,轻点我们保存其所有连出去的边

显然重点不会超过\(sqrt{边总数}\)个,且重点和轻点所连出去的边不会超过\(sqrt{边总数}\)条

每个重点要记录它连出去的到达黑点的边的总权值和到达白点的边的总权值

对于每次修改操作,分轻重点分别维护

  • 如果修改的是轻点,那么直接暴力修改答案
  • 如果是重点,利用保存的连出去的边到达的两种颜色的权值和更新答案

    同时每次修改一个点,需要更新其连的重点的两个总权值数据

对于查询操作直接输出记录的答案即可

查询复杂度\(O(1)\)

修改复杂度\(O(sqrt{边总数})\)

总时间复杂度为\(O(q sqrt{边总数})\)

只给了\(32MB\)的空间,很容易爆内存

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
typedef long long int LL;
int n,m,col[MAXN],deg[MAXN];
LL vtot[3],val[2][MAXN];
bool heavy[MAXN];
vector<pair<int,LL>> G[MAXN];
char op[10];
void solvequery(){
scanf("%s",op);
if(op[0]=='A'){
int x, y;
scanf("%d %d",&x,&y);
printf("%I64d\n",vtot[x+y]);
}
else{
int x; scanf("%d",&x);
if(heavy[x]){
vtot[1+col[x]] -= val[1][x]; vtot[0+col[x]] -= val[0][x];
vtot[1+(col[x]^1)] += val[1][x]; vtot[0+(col[x]^1)] += val[0][x];
}
else{
for(auto e : G[x]){
vtot[col[x]+col[e.first]] -= e.second;
vtot[(col[x]^1)+col[e.first]] += e.second;
}
}
for(auto e : G[x]){
if(!heavy[e.first]) continue;
val[col[x]][e.first] -= e.second;
val[col[x]^1][e.first] += e.second;
}
col[x] ^= 1;
}
}
pair<pair<int,int>,LL> vec[MAXN];
void solve(int kase){
for(int i = 1; i <= n; i++){
scanf("%d",&col[i]);
G[i].clear();
val[0][i] = val[1][i] = deg[i] = 0;
}
vtot[0] = vtot[1] = vtot[2] = 0;
int tot = 0;
for(int i = 1; i <= m; i++){
int u, v, w; scanf("%d %d %d",&u,&v,&w);
if(u>v) u ^= v ^= u ^= v;
vec[++tot] = make_pair(make_pair(u,v),w);
}
sort(vec+1,vec+1+tot);
int nt = 1;
for(int i = 2; i <= tot; i++){
if(vec[i].first==vec[nt].first) vec[nt].second += vec[i].second;
else vec[++nt] = vec[i];
}
for(int i = 1; i <= nt; i++) deg[vec[i].first.first]++, deg[vec[i].first.second]++;
int up = sqrt(nt);
for(int i = 1; i <= n; i++) heavy[i] = deg[i]>=up;
for(int i = 1; i <= nt; i++){
auto &e = vec[i];
int u = e.first.first, v = e.first.second;
LL w = e.second;
if(heavy[u]){
if(heavy[v]) G[u].push_back(make_pair(v,w));
val[col[v]][u] += w;
}
else G[u].push_back(make_pair(v,w));
if(heavy[v]){
if(heavy[u]) G[v].push_back(make_pair(u,w));
val[col[u]][v] += w;
}
else G[v].push_back(make_pair(u,w));
vtot[col[u]+col[v]] += w;
}
int q; scanf("%d",&q);
printf("Case %d:\n",kase);
while(q--) solvequery();
}
int main(){
int kase = 0;
while(scanf("%d %d",&n,&m)!=EOF) solve(++kase);
return 0;
}

最新文章

  1. DDD 领域驱动设计-看我如何应对业务需求变化,愚蠢的应对?
  2. 不定义JQuery插件,不要说会JQuery 分类: JavaScript 2014-11-24 14:18 155人阅读 评论(0) 收藏
  3. ubuntu14.04LTS编译MUDOS v22.2b14
  4. 集合的知识点梳理(List,Set,不包含泛型)
  5. 两个基于C++/Qt的开源WEB框架
  6. java文件处理工具类
  7. arry()数组的理解及api的使用(二)
  8. iTunes制作iPhone手机铃声方法(mac版2017年4月更新)
  9. LinkedHashMap源码分析及实现LRU
  10. offsetLeft、offsetX等
  11. Generic XXE Detection
  12. Vue Resource root options not used?
  13. Disruptor入门
  14. 为PartialView传递一个参数
  15. 转 微软Sysinternals Suite工具13年12月版下载
  16. quartz 的简单使用
  17. CCF CSP 201403-2 窗口
  18. 用压测模拟并发、并发处理(synchronized,redis分布式锁)
  19. git忽略某个文件夹
  20. 微信WeUI常见页面模板

热门文章

  1. Windows软件Everything的配置
  2. 如何用Github上传项目中的代码
  3. 有了链路日志增强,排查Bug小意思啦!
  4. 18.java设计模式之中介者模式
  5. APP测试之Monkey测试
  6. [GKCTF2020]老八小超市儿
  7. Jquery实现对Array数组实现类似Linq的Lambda表达式的Where方法筛选
  8. RESTful风格、异常处理、Spring框架
  9. PCB导线长宽与电源压降
  10. celery 原理