bzoj 2816: [ZJOI2012]网络(splay)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=2816
【题意】
给定一个无向图,满足条件:从一个节点出发的同色边不超过2条,且不存在同色环。要求提供修改节点权值,修改边的颜色,查询同色边c构成的图中u->v路径上节点的最大权值。
【思路】
根据满足的条件,可以判断同色的图构成了若干条一条链。
考虑使用splay维护这些链:
对于每个图上的点建C个splay结点。这里需要splay提供将结点u旋转到根的操作,所以需要维护一个fa指针指向父亲,直接定位到结点u地址,先把该点到root路径上的所有标记下传,然后将u从下向上旋转至根。
对于点修改:将u的所有颜色的结点修改。
对于边修改:设oldc为原来边的颜色w为新颜色,uv为边的端点。将oldc颜色的u,v之间断开,然后把w颜色的uv连接。这里用到split和merge的操作。考虑merge,先将u,v splay至根,这时候一定满足u,v必有一个儿子为空(否则提前输出错误),如果出现u,v是相同儿子为空的情况,我们需要反转u的序列然后连接,所以splay还要维护一个rev的懒标记。
对于查询:将u旋转到根,v旋转到u的一个儿子,假设位于d。u以及v以及v的d^1儿子构成了u..v之间的序列,这里可以加一个ori表示原来该节点代表的值,则答案为max{u->ori,v->ori,v->ch[d^1]->v}。
【代码】
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
typedef pair<int,int> edge;
const int N = 5e4+;
const int M = 5e5+; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int v,w,nxt;
}e[M];
int en=,front[N];
void adde(int u,int v,int w)
{
e[++en]=(Edge){v,w,front[u]}; front[u]=en;
} struct Node *null;
struct Node {
Node *ch[],*fa;
int v,ori,rev;
void init(int x) {
v=ori=x; rev=;
ch[]=ch[]=fa=null;
}
void maintain() {
v=max(ori,max(ch[]->v,ch[]->v));
}
void pushdown() {
if(rev) {
swap(ch[],ch[]);
ch[]->rev^=,ch[]->rev^=;
rev=;
}
}
}*node[N][],nodepool[N*]; void rot(Node *o, int d) {
Node *k=o->ch[d],*tmp=null;
o->ch[d]=k->ch[d^];
if((tmp=k->ch[d^])!=null) tmp->fa=o;
k->ch[d^]=o;
if((tmp=o->fa)!=null) tmp->ch[tmp->ch[]==o]=k;
o->fa=k; k->fa=tmp;
}
void up_push(Node* u) {
static Node* st[N]; int top=;
while(u!=null) {
st[++top]=u;
u=u->fa;
}
while(top)
st[top--]->pushdown();
}
void splay(Node* u,Node* des=null) {
up_push(u);
Node *nf,*nff;
while(u!=des && (nf=u->fa)!=des) {
nff=nf->fa;
if(nff==des) rot(nf,nf->ch[]==u),nf->maintain();
else {
int d1=nf->ch[]==u,d2=nff->ch[]==nf;
if(d1==d2) rot(nff,d2),rot(nf,d1);
else rot(nf,d1),rot(nff,d2);
nff->maintain(),nf->maintain();
}
}
u->maintain();
}
void reverse(Node* u) {
swap(u->ch[],u->ch[]);
u->ch[]->rev^=;
u->ch[]->rev^=;
}
void split(Node* u,Node* v) {
splay(u); splay(v,u);
int d=u->ch[]==v;
u->ch[d]=null,v->fa=null;
u->maintain();
}
void merge(Node* u,Node* v) {
splay(u); splay(v);
if(u->ch[]==null&&v->ch[]==null) u->ch[]=v;
else if(u->ch[]==null&&v->ch[]==null) u->ch[]=v;
else {
reverse(u);
if(u->ch[]==null) u->ch[]=v;
else u->ch[]=v;
}
v->fa=u;
u->maintain();
} int n,m,C,K;
int col_cnt[N][],col_vis[N][],q[N],a[N];
map<pair<int,int>,int> mp; Node* build(int l,int r,Node* fa,int* q,int c) {
if(r<l) return null;
int mid=l+r>>;
Node *u=node[q[mid]][c];
u->init(a[q[mid]]);
u->fa=fa;
u->ch[]=build(l,mid-,u,q,c);
u->ch[]=build(mid+,r,u,q,c);
u->maintain();
return u;
}
void bfs(int u,int c) {
static int q[M],f,r;
f=r=;
col_vis[u][c]=;
q[r++]=u;
while(f<r) {
int u=q[f++];
trav(u,i) if(e[i].w==c&&!col_vis[e[i].v][c]){
col_vis[e[i].v][c]=;
q[r++]=e[i].v;
break;
}
}
build(,r-,null,q,c);
} int connect(Node* u,Node* v) {
splay(u); splay(v);
return u->fa!=null;
}
int querymax(Node* u,Node* v) {
splay(u),splay(v,u);
int d=v==u->ch[];
return max(max(u->ori,v->ori),v->ch[d^]->v);
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
null=new Node();
n=read(),m=read(),C=read(),K=read();
FOR(i,,n) a[i]=read();
FOR(i,,m) {
int u=read(),v=read(),w=read();
w++;
adde(u,v,w),adde(v,u,w);
col_cnt[u][w]++;
col_cnt[v][w]++;
if(u>v) swap(u,v);
mp[make_pair(u,v)]=w;
}
FOR(i,,n) FOR(j,,C) {
node[i][j]=&nodepool[(i-)*C+j-];
node[i][j]->init(); //³õʼ»¯ÄÚ´æ³Ø
}
FOR(i,,C) FOR(j,,n)
if(!col_vis[j][i]&&col_cnt[j][i]==) bfs(j,i);
FOR(i,,K) {
int op=read(),x,y,w;
if(x>y) swap(x,y);
if(op==) {
x=read(),y=read();
a[x]=y;
FOR(i,,C) {
splay(node[x][i]);
node[x][i]->ori=node[x][i]->v=y;
node[x][i]->maintain();
}
} else
if(op==) {
x=read(),y=read();
if(x>y) swap(x,y);
w=read(); w++;
if(!mp.count(make_pair(x,y))) puts("No such edge.");
else {
int old=mp[make_pair(x,y)];
if(old==w) { puts("Success."); continue; }
if(col_cnt[x][w]+> || col_cnt[y][w]+>) puts("Error 1.");
else if(connect(node[x][w],node[y][w])) puts("Error 2.");
else {
split(node[x][old],node[y][old]);
merge(node[x][w],node[y][w]);
--col_cnt[x][old];
--col_cnt[y][old];
++col_cnt[x][w];
++col_cnt[y][w];
mp[make_pair(x,y)]=w;
puts("Success.");
}
}
} else {
w=read(); w++;
x=read(),y=read();
if(x==y) printf("%d\n",a[x]);
else if(!connect(node[x][w],node[y][w])) puts("-1");
else printf("%d\n",querymax(node[x][w],node[y][w]));
}
}
return ;
}
P.S. 第一次写这种splay,代码借鉴别人的,又涨姿势了 ฅ(๑˙o˙๑)ฅ
bzoj 2816: [ZJOI2012]网络(splay)的更多相关文章
- bzoj 2816: [ZJOI2012]网络 (LCT 建多棵树)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2816 题面: http://www.lydsy.com/JudgeOnline/upload ...
- BZOJ.2816.[ZJOI2012]网络(LCT)
题目链接 BZOJ 洛谷 对每种颜色维护一个LCT,保存点之间的连接关系. 修改权值A[x]和所有Max[x]都要改: 修改边的颜色先枚举所有颜色,看是否在某种颜色中有边,然后断开.(枚举一遍就行啊 ...
- 【刷题】BZOJ 2816 [ZJOI2012]网络
Description http://www.lydsy.com/JudgeOnline/upload/zjoi2012.pdf Solution 维护树上联通块的信息,支持动态加边删边 LCT 总共 ...
- 洛谷 2173 BZOJ 2816 [ZJOI2012]网络
[题解] 明显的LCT模板题,c种颜色就开c棵LCT好了.. #include<cstdio> #include<algorithm> #define N 100010 #de ...
- 2816: [ZJOI2012]网络
传送们 把一个点拆成c个即可 浪费时间的水题... //Achen #include<algorithm> #include<iostream> #include<cst ...
- 洛谷 P2173 [ZJOI2012]网络 解题报告
P2173 [ZJOI2012]网络 题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相同颜色的边不超过两条. 图中不存在同色的环, ...
- AC日记——[ZJOI2012]网络 bzoj 2816
2816 思路: 多个LCT: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 10005 #define l ...
- [ZJOI2012][bzoj 2816] 网络 network [LCT]
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2816 思路: 第一个条件看完暂时还没什么想法 看完第二个,发现每一个颜色都是一个森林 进而想 ...
- bzoj千题计划223:bzoj2816: [ZJOI2012]网络
http://www.lydsy.com/JudgeOnline/problem.php?id=2816 每种颜色搞一个LCT 判断u v之间有边直接相连: 如果u和v之间有边相连,那么他们的深度相差 ...
随机推荐
- 【贪心】bzoj 3709:[PA2014]Bohater
3709: [PA2014]Bohater Time Limit: 5 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 653 Solved: ...
- HashTable、HashMap、LinkedHashMap、TreeMap的比较
HashTable:继承自Dictionary类,实现了Map接口,不允许键或值为空,线程同步: HashMap:继承自AbstractMap类,实现了Map接口,允许键或值为空,线程不同步: Lin ...
- c++ 成员指针函数 实现委托----跨平台实现(复杂)
牛逼: c++ 牵涉到的技术细节太多了,为了实现一个委托,他妈都搞到汇编里面去了... 总结 为了解释一小段代码,我就得为这个语言中具有争议的一部分写这么一篇长长的指南.为了两行汇编代码,就要做如此麻 ...
- 我见过的 Objective-C, 讲的最通俗易懂的入门教程....
http://www.cnblogs.com/mjios/category/454764.html ---- 给力...
- nginx的负载均衡和反响代理配置
4. 负载均衡配置 nginx 的 upstream默认是以轮询的方式实现负载均衡,这种方式中,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. 另外 ...
- POJ 1879 Tempus et mobilius Time and motion 队列和栈
很简单的队列和栈的应用,不过读明白题意非常重要:(直接引用白书的题解)三个轨道,一个库.分别是分钟单位的轨道,5min单位的轨道,一小时单位的轨道,还有就是n容量的库.每过一分钟,一个小球从库里面出来 ...
- IOS,Object C学习过程中遇到的attributes
@property 定义一个属性 @synthesize 告诉编译器自动为属性自动生成 getter 和setter方法 在定义属性的时候会用到如下@attributes nonatomic,告诉编译 ...
- JavaBean个人总结
JavaBean在JSP程序中的应用 JavaBean是为Java语言设计的软件组件模型,具有可重复使用和跨平台的特点.可以通过JavaBean来封装业务逻辑,进行数据库操作等,从而很好的实现业务逻辑 ...
- Shell中判断字符串是否为数字的6种方法分享
#!/bin/bash ## 方法1 a=1234;echo "$a"|[ -n "`sed -n '/^[0-9][0-9]*$/p'`" ] &&a ...
- Spring-Data-JPA学习
Spring-Data-JPA结构图 网址: http://blog.sina.com.cn/s/blog_667ac0360102ecsf.html