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之间有边相连,那么他们的深度相差 ...
随机推荐
- BZOJ3404: [Usaco2009 Open]Cow Digit Game又见数字游戏
3404: [Usaco2009 Open]Cow Digit Game又见数字游戏 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 47 Solved ...
- Amzon MWS API开发之订单接口
Amazon订单接口是Amazon MWS 开发接口中的一大块,我们可以通过接口调用来获得订单数据. 在调用接口之前,首先我们要获得相关店铺商家的店铺密钥等信息.如下: 在此我将所有信息定义在一个类中 ...
- jquery中事件重复绑定以及解绑问题
一般的情况下,对于这种情况,我们常规的思路是,先解绑,再绑定,如下: $(selector).unbind('click').bind('click',function(){....}); 当这样会有 ...
- Qt: 访问容器(三种方法,加上for循环就四种了)good
#include <iostream>#include <QString>#include <QList>#include <QListIterator> ...
- 编译qt-mobility
因为用到了qt-mobility,必须自己编译一下,参考列出了参考资料. 参考: 1. windows下编译qt-mobility http://hi.baidu.com/xchinux/blog/ ...
- CentOS7 64位 自动分配IP地址设置
vim /etc/sysconfig/network-scripts/ifcfg-eno16777736 # ifcfg-后接网卡名称 配置如下,ONBOOT设置为yes HWADDR=:0C::E9 ...
- objective C中数据持久化方式1--对象归档
第一.数据持久化的方式: NSKeyedArchiver--对象归档 属性列表化(NSArray.NSDictionary.NSUserDefault) SQlite数据库.CoreData数据库 其 ...
- 【HDOJ】3553 Just a String
后缀数组加二分可解. /* 3553 */ #include <iostream> #include <sstream> #include <string> #in ...
- HashMap Hashtable ArrayList HashSet
一.散列 1. HashMap 1) hashmap的数据结构 Hashmap是一个数组和链表的结合体(在数据结构称“链表散列“),如下图示: 当我们往hashmap中put元素的时候,先根据key ...
- 通过ngx-lua来统计Nginx上的虚拟主机性能数据
Web server调研分析 Filed under: Web Server — cmpan @ 2012-10-29 20:38:34 摘要 简单可依赖的架构首先需要有一个简单可依赖的前端WebSe ...