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之间有边相连,那么他们的深度相差 ...
随机推荐
- c++ 发布动态.so
原文地址 代码改变世界 Posts - 105, Articles - 0, Comments - 1561 Cnblogs Dashboard Logout Home Contact Gallery ...
- C++: 单例模式和缺陷
C++: 单例模式和缺陷 实现一个单例模式 1 class Singleton { 2 private: 3 Singleton() { cout << " ...
- ZOJ 1008 Gnome Tetravex(DFS)
题目链接 题意 : 将n*n个正方形进行排列,需要判断相邻的正方形的相邻三角形上边的数字是不是都相等. 思路 : 只知道是个深搜,一开始不知道怎么搜,后来看了题解才明白,就是说不是自己去搜,而是将给定 ...
- 使用IDEA自带maven建java项目时报错。
今天用IDEA建立maven项目时报错: [INFO] Scanning for projects... [INFO] Searching repository for plugin with pre ...
- [itint5]任务调度
http://www.itint5.com/oj/#10 拓扑排序.首先按照题目给出的数据结构复杂度不会是O(v+e)的,所以先要变换数据结构.二来写的时候用一个stack会更好点.还有就是题目里其实 ...
- Nginx-location配置指南
语法规则: location [=|~|~*|^~] /uri/ { … } = 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可.nginx不对url做编码,因 ...
- AD15高版软件卡不卡,问题解决大讨论
AD高版软件很卡(包括13 14 15版),这是我遇到过的问题,大家都遇到过的问题, 这里我分享一个解决办法:也请给位有什么好的方法也一起分享. 问题1卡:打开AD15软件, 按住鼠标中键 放大 或 ...
- Linux的终端与进程
原文链接:http://os.51cto.com/art/201104/256477.htm Linux的普通进程(守护进程除外) 是终端的子进程,进程的存在要依赖终端为其提供空间包括标准输入.标准输 ...
- Xcode中的iOS工程模板
1. Application类型 我们大部分的开发工作都是从使用Application类型模板创建iOS程序开始的.该类型共包含7个模板,具体如下所示. Master-Detail Applicati ...
- 页面滚动动态加载数据,页面下拉自动加载内容 jquery
<!DOCTYPE=html> <html> <head> < script src="js/jquery.js" type=" ...