【题目链接】

http://www.lydsy.com/JudgeOnline/problem.php?id=2959

【题意】

n个点,提供操作:连边,修改点权,查询自定义边的方向后起点a终点b能经过的最大点权和。

【思路】

对于一个边的双连通分量,显然可以将权值全部获得。

如果没有连边操作,我们只需要将一个bcc缩点后求得a->b路径上的点权和即可。

加上连边后,使用并查集代表一个bcc,如果u,v之间不连通直接连边,如果已经连通则构成一个bcc,使用并查集将LCT的所有节点合并。

注意缩点后以并查集的代表元为该点,Access上找父亲的时候应该用父亲的bcc代表元。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 3e5+; 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 UFS {
int p[N];
int ifind(int x) {
if(p[x]==||x==p[x]) return p[x]=x;
return p[x]=ifind(p[x]);
}
void iunion(int x,int y) {
x=ifind(x),y=ifind(y);
if(x!=y) p[x]=y;
}
} bcc,S; namespace LCT { struct Node {
Node *ch[],*fa;
int v,rev,sum;
Node() {}
Node(int x) ;
void reverse() {
rev^=;
swap(ch[],ch[]);
}
void up_push() {
if(fa->ch[]==this||fa->ch[]==this)
fa->up_push();
if(rev) {
ch[]->reverse();
ch[]->reverse();
rev=;
}
}
void maintain() {
sum=v+ch[]->sum+ch[]->sum;
}
} T[N],*null=&T[];
Node::Node(int x) {
rev=;
v=sum=x;
ch[]=ch[]=fa=null;
} void rot(Node* o,int d) {
Node *p=o->fa;
p->ch[d]=o->ch[d^];
o->ch[d^]->fa=p;
o->ch[d^]=p;
o->fa=p->fa;
if(p==p->fa->ch[])
p->fa->ch[]=o;
else if(p==p->fa->ch[])
p->fa->ch[]=o;
p->fa=o;
p->maintain();
}
void splay(Node *o) {
o->up_push();
Node *nf,*nff;
while(o->fa->ch[]==o||o->fa->ch[]==o) {
nf=o->fa,nff=nf->fa;
if(o==nf->ch[]) {
if(nf==nff->ch[]) rot(nf,);
rot(o,);
} else {
if(nf==nff->ch[]) rot(nf,);
rot(o,);
}
}
o->maintain();
}
void Access(Node *o) {
Node *son=null;
while(o!=null) {
splay(o);
o->ch[]=son;
o->maintain();
o->fa=&T[bcc.ifind(o->fa-T)];
son=o; o=o->fa;
}
}
void evert(Node *o) {
Access(o);
splay(o);
o->reverse();
}
void Link(Node *u, Node *v) {
evert(u);
u->fa=v;
} } using namespace LCT; int n,m,a[N]; void merge(Node* &u,Node* v)
{
if(u==null) return ;
v->v+=u->v;
bcc.iunion(u-T,v-T);
merge(u->ch[],v);
merge(u->ch[],v);
u=null;
} int main()
{
n=read(),m=read();
FOR(i,,n) {
a[i]=read(); T[i]=Node(a[i]);
}
int op,u,v;
FOR(i,,m) {
op=read(),u=read(),v=read();
if(op==) {
u=bcc.ifind(u),v=bcc.ifind(v);
if(u==v) continue;
if(S.ifind(u)!=S.ifind(v))
Link(&T[u],&T[v]),
S.iunion(u,v);
else {
evert(&T[u]);
Access(&T[v]),splay(&T[v]);
merge(T[v].ch[],&T[v]);
merge(T[v].ch[],&T[v]);
T[v].maintain();
}
} else
if(op==) {
splay(&T[bcc.ifind(u)]);
T[bcc.ifind(u)].v+=v-a[u];
T[bcc.ifind(u)].maintain();
a[u]=v;
} else {
u=bcc.ifind(u),v=bcc.ifind(v);
if(S.ifind(u)!=S.ifind(v)) puts("-1");
else {
evert(&T[u]);
Access(&T[v]),splay(&T[v]);
printf("%d\n",T[v].sum);
}
}
}
return ;
}

Q:打码的最怕什么

A:手残和眼瞎。

真不巧,我两样都是

最新文章

  1. sqlHelper做增删改查,SQL注入处理,存储值,cookie,session
  2. PHP中array_chunk的用法
  3. Xamarin迁移到 Unified API 注意事项
  4. 使单元格td内部都是超链接
  5. NOIP200503采药
  6. Android开源库--Universal Image Loader通用图片加载器
  7. 【LeetCode】232 &amp; 225 - Implement Queue using Stacks &amp; Implement Stack using Queues
  8. Enum(枚举)示例
  9. Scrum中的User Story
  10. Android JNI入门第二篇——Java参数类型与本地参数类型对照
  11. svn创建并应用补丁
  12. Linq无聊练习系列6--Any/All/Contains/Concat/Union/Intersect/Except/take/skip/SqlMethods操作练习
  13. chromedriver禁用图片,禁用js,切换UA
  14. Stars HDU - 1541
  15. jQuery入门基础(选择器)
  16. Apache Commons FileUpload 实现文件上传
  17. Linux_问题
  18. requests库入门03-get请求
  19. PyCharm笔记之配色方案和取消波浪线
  20. MyEclipse教程:使用UML创建模块库——第二部分(一)

热门文章

  1. Unix编程之size_t、ssize_t
  2. Unity打包APK横屏时的注意事项
  3. JavaWeb项目开发案例精粹-第2章投票系统-005实体层
  4. Android sendMessage 与 obtainMessage (sendToTarget)比较
  5. Maven远程仓库
  6. 轻量级MVC标准
  7. ios7新增基础类库以及OC新特性
  8. WIN7 64位系统搭建WINCE6.0系统遇到的问题
  9. C++ STL之deque的基本操作
  10. CFF前端沙龙总结