搞了一上午LCT,真是累死了……

以前总觉得LCT高大上不好学不好打,今天打了几遍感觉还可以嘛= =反正现在的水平应付不太难的LCT题也够用了,就这样好了,接下来专心搞网络流。

话说以前一直YY不出来LCT怎么维护边权,多谢sxysxy告诉我要添虚点来把边权转化为点权,感激不尽……

言归正传。

[国家集训队2012]tree(伍一鸣)

LCT模板题嘛……

区间乘和区间加一遍写对,感觉费了好多rp……

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x)))
#define dir(x) ((x)==(x)->p->ch[1])
using namespace std;
typedef unsigned uint;
const int maxn=;
const uint M=51061u;
struct node{
uint data,sm,a,b;
int size;
node *ch[],*p;
bool rev;
node(uint d=0u):data(d),sm(d),a(1u),b(0u),size(),rev(false){}
void add(uint d){
sm+=(uint)size%M*d%M;sm%=M;
data+=d;data%=M;
b+=d;b%=M;
}
void mul(uint d){
sm*=d;sm%=M;
data*=d;data%=M;
b*=d;b%=M;
a*=d;a%=M;
}
void pushdown(){
if(rev){
ch[]->rev^=true;
ch[]->rev^=true;
swap(ch[],ch[]);
rev=false;
}
if(a!=){
ch[]->mul(a);
ch[]->mul(a);
a=1u;
}
if(b){
ch[]->add(b);
ch[]->add(b);
b=0u;
}
}
void refresh(){
size=ch[]->size+ch[]->size+;
sm=ch[]->sm+ch[]->sm;sm%=M;sm+=data;sm%=M;
}
}nodes[maxn],*null=nodes;
void dfs(int);
void add(node*,node*,uint);
void mul(node*,node*,uint);
uint qsum(node*,node*);
node *access(node*);
void makeroot(node*);
void link(node*,node*);
void cut(node*,node*);
void splay(node*);
void rot(node*,int);
vector<int>G[maxn];
int n,m,prt[maxn]={},x,y;
uint d;
char c;
int main(){
freopen("nt2012_wym_tree.in","r",stdin);
freopen("nt2012_wym_tree.out","w",stdout);
null->ch[]=null->ch[]=null->p=null;
null->size=;
scanf("%d%d",&n,&m);
for(int i=;i<n;i++){
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs();
for(int i=;i<=n;i++){
nodes[i]=node();
nodes[i].ch[]=nodes[i].ch[]=null;
nodes[i].p=nodes+prt[i];
}
while(m--){
scanf(" %c%d%d",&c,&x,&y);
if(c=='+'){
scanf("%u",&d);
add(nodes+x,nodes+y,d);
}
else if(c=='-'){
cut(nodes+x,nodes+y);
scanf("%d%d",&x,&y);
link(nodes+x,nodes+y);
}
else if(c=='*'){
scanf("%u",&d);
mul(nodes+x,nodes+y,d);
}
else if(c=='/')printf("%u\n",qsum(nodes+x,nodes+y));
}
return ;
}
void dfs(int x){
for(int i=;i<(int)G[x].size();i++)if(G[x][i]!=prt[x]){
prt[G[x][i]]=x;
dfs(G[x][i]);
}
}
void add(node *x,node *y,uint d){
makeroot(x);
access(y)->add(d);
}
void mul(node *x,node *y,uint d){
makeroot(x);
access(y)->mul(d);
}
uint qsum(node *x,node *y){
makeroot(x);
return access(y)->sm;
}
node *access(node *x){
node *y=null;
while(x!=null){
splay(x);
x->ch[]=y;
(y=x)->refresh();
x=x->p;
}
return y;
}
void makeroot(node *x){
access(x);
splay(x);
x->rev^=true;
}
void link(node *x,node *y){
makeroot(x);
x->p=y;
}
void cut(node *x,node *y){
makeroot(x);
access(y);
splay(y);
x->p=null;
y->ch[]=null;
y->refresh();
}
void splay(node *x){
x->pushdown();
while(!isroot(x)){
if(!isroot(x->p))x->p->p->pushdown();
x->p->pushdown();
x->pushdown();
if(isroot(x->p)){
rot(x->p,dir(x)^);
break;
}
if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^);
else rot(x->p,dir(x)^);
rot(x->p,dir(x)^);
}
}
void rot(node *x,int d){
node *y=x->ch[d^];
x->ch[d^]=y->ch[d];
if(y->ch[d]!=null)y->ch[d]->p=x;
y->p=x->p;
if(!isroot(x))x->p->ch[dir(x)]=y;
y->ch[d]=x;
x->p=y;
x->refresh();
y->refresh();
}

[Sdoi2008]Cave 洞穴勘测

也是LCT维护森林连通性的模板题。

话说一开始读错题了,以为是一般图,就写了一发分治并查集,然后发现LCT又好写又跑得快……

分治并查集的代码长度亮了……

分治并查集:

/**************************************************************
Problem: 2049
User: hzoier
Language: C++
Result: Accepted
Time:4988 ms
Memory:58572 kb
****************************************************************/ #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int maxn=,maxm=;
inline int randint(){
static int a=,b=,c=,x=,p=;
x=a*x*x+b*x+c;x%=p;x+=p;
return x%=p;
}
void addedge(int,int,int);
void addquery(int,int,int);
void solve(int,int,int);
int findroot(int);
void mergeset(int,int,vector<int>&);
int prt[maxn];
map<pair<int,int>,int>mp;
vector<int>u[maxm<<],v[maxm<<],stk[maxm<<];
int qu[maxm<<]={},qv[maxm<<];
int n,m,x,y,s,t;
char c[];
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)prt[i]=i;
for(int i=;i<=m;i++){
scanf("%s%d%d",c,&x,&y);
if(x>y)swap(x,y);
if(*c=='C'){
if(!mp.count(make_pair(x,y)))mp[make_pair(x,y)]=i;
}
else if(*c=='D'){
s=mp[make_pair(x,y)];
t=i;
addedge(,m,);
mp.erase(make_pair(x,y));
}
else{
t=i;
addquery(,m,);
}
}
t=m;
for(map<pair<int,int>,int>::iterator it=mp.begin();it!=mp.end();it++){
x=it->first.first;
y=it->first.second;
s=it->second;
addedge(,m,);
}
solve(,m,);
return ;
}
void addedge(int l,int r,int rt){
if(s<=l&&t>=r){
u[rt].push_back(x);
v[rt].push_back(y);
return;
}
int mid=(l+r)>>;
if(s<=mid)addedge(l,mid,rt<<);
if(t>mid)addedge(mid+,r,rt<<|);
}
void addquery(int l,int r,int rt){
qu[rt]|=x;
if(l==r){
qv[rt]=y;
return;
}
int mid=(l+r)>>;
if(t<=mid)addquery(l,mid,rt<<);
else addquery(mid+,r,rt<<|);
}
void solve(int l,int r,int rt){
if(!qu[rt])return;
for(int i=;i<(int)u[rt].size();i++)mergeset(u[rt][i],v[rt][i],stk[rt]);
if(l==r)printf(findroot(qu[rt])==findroot(qv[rt])?"Yes\n":"No\n");
else{
int mid=(l+r)>>;
solve(l,mid,rt<<);
solve(mid+,r,rt<<|);
}
if(!stk[rt].empty())for(int i=(int)stk[rt].size()-;i>=;i--)prt[stk[rt][i]]=stk[rt][i];
}
void mergeset(int x,int y,vector<int>&a){
x=findroot(x);y=findroot(y);
if(x==y)return;
if(randint()&)swap(x,y);
prt[x]=y;
a.push_back(x);
}
int findroot(int x){
while(prt[x]!=x)x=prt[x];
return x;
}

LCT:

 /**************************************************************
Problem: 2049
User: hzoier
Language: C++
Result: Accepted
Time:1656 ms
Memory:976 kb
****************************************************************/ #include<cstdio>
#include<cstring>
#include<algorithm>
#define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x)))
#define dir(x) ((int)((x)==(x)->p->ch[1]))
using namespace std;
const int maxn=;
struct node{
bool rev;
node *ch[],*p;
node():rev(false){}
void pushdown(){
if(!rev)return;
ch[]->rev^=true;
ch[]->rev^=true;
swap(ch[],ch[]);
rev=false;
}
}nodes[maxn],*null=nodes;
node *access(node*);
void makeroot(node*);
void link(node*,node*);
void cut(node*,node*);
node *findroot(node*);
void splay(node*);
void rot(node*,int);
int n,m,x,y;
char c[];
int main(){
null->ch[]=null->ch[]=null->p=null;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)nodes[i].ch[]=nodes[i].ch[]=nodes[i].p=null;
while(m--){
scanf("%s%d%d",c,&x,&y);
if(*c=='C')link(nodes+x,nodes+y);
else if(*c=='D')cut(nodes+x,nodes+y);
else printf(findroot(nodes+x)==findroot(nodes+y)?"Yes\n":"No\n");
}
return ;
}
node *access(node *x){
node *y=null;
while(x!=null){
splay(x);
x->ch[]=y;
y=x;
x=x->p;
}
return y;
}
void makeroot(node *x){
access(x);
splay(x);
x->rev^=true;
}
void link(node *x,node *y){
makeroot(x);
x->p=y;
}
void cut(node *x,node *y){
makeroot(x);
access(y);
splay(y);
y->ch[]=null;
x->p=null;
}
node *findroot(node *x){
access(x);
splay(x);
while(x->pushdown(),x->ch[]!=null)x=x->ch[];
return x;
}
void splay(node *x){
x->pushdown();
while(!isroot(x)){
if(!isroot(x->p))x->p->p->pushdown();
x->p->pushdown();
x->pushdown();
if(isroot(x->p)){
rot(x->p,dir(x)^);
break;
}
if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^);
else rot(x->p,dir(x)^);
rot(x->p,dir(x)^);
}
}
void rot(node *x,int d){
node *y=x->ch[d^];
x->ch[d^]=y->ch[d];
if(y->ch[d]!=null)y->ch[d]->p=x;
y->p=x->p;
if(!isroot(x))x->p->ch[dir(x)]=y;
y->ch[d]=x;
x->p=y;
}

COGS29 公路建设

只有加边的动态MST,LCT维护即可。

注意加虚点来维护边权。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x)))
#define dir(x) ((int)((x)==(x)->p->ch[1]))
using namespace std;
const int maxn=;
struct node{
int data,mx,pos;
node *ch[],*p;
bool rev;
node(int d):data(d),mx(d),pos(-),rev(false){}
void pushdown(){
if(!rev)return;
if(pos!=-)pos^=;
ch[]->rev^=true;
ch[]->rev^=true;
swap(ch[],ch[]);
rev=false;
}
void refresh(){
mx=data;
pos=-;
if(ch[]->mx>mx){
mx=ch[]->mx;
pos=;
}
if(ch[]->mx>mx){
mx=ch[]->mx;
pos=;
}
}
}*null=new node(-);
node *newnode(int);
node *access(node*);
void makeroot(node*);
void cut(node*,node*);
void link(node*,node*);
node *getroot(node*);
node *getmax(node*,node*);
void splay(node*);
void rot(node*,int);
map<node*,pair<node*,node*> >mp;
node *iter[maxn];
int n,m,cnt=,x,y,w,ans=;
node *tmp;
int main(){
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
null->ch[]=null->ch[]=null->p=null;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)iter[i]=newnode(-);
while(m--){
scanf("%d%d%d",&x,&y,&w);
if(getroot(iter[x])!=getroot(iter[y])){
tmp=newnode(w);
mp[tmp]=make_pair(iter[x],iter[y]);
link(tmp,iter[x]);
link(tmp,iter[y]);
ans+=w;
cnt++;
}
else{
node *tmp=getmax(iter[x],iter[y]);
if(tmp->data>w){
ans-=tmp->data;
cut(tmp,mp[tmp].first);
cut(tmp,mp[tmp].second);
tmp->data=w;
mp[tmp]=make_pair(iter[x],iter[y]);
link(tmp,iter[x]);
link(tmp,iter[y]);
ans+=w;
}
}
if(cnt==n-)printf("%.1lf\n",(double)ans/2.0);
else printf("0\n");
}
return ;
}
node *newnode(int d){
node *x=new node(d);
x->ch[]=x->ch[]=x->p=null;
return x;
}
node *access(node *x){
node *y=null;
while(x!=null){
splay(x);
x->ch[]=y;
(y=x)->refresh();
x=x->p;
}
return y;
}
void makeroot(node *x){
access(x);
splay(x);
x->rev^=true;
}
void cut(node *x,node *y){
makeroot(x);
access(y);
splay(y);
x->p=null;
y->ch[]=null;
y->refresh();
}
void link(node *x,node *y){
makeroot(x);
x->p=y;
}
node *getroot(node *x){
x=access(x);
while(x->pushdown(),x->ch[]!=null)x=x->ch[];
splay(x);
return x;
}
node *getmax(node *x,node *y){
makeroot(x);
x=access(y);
while(x->pushdown(),x->pos!=-)x=x->ch[x->pos];
return x;
}
void splay(node *x){
x->pushdown();
while(!isroot(x)){
if(!isroot(x->p))x->p->p->pushdown();
x->p->pushdown();
x->pushdown();
if(isroot(x->p)){
rot(x->p,dir(x)^);
break;
}
if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^);
else rot(x->p,dir(x)^);
rot(x->p,dir(x)^);
}
}
void rot(node *x,int d){
node *y=x->ch[d^];
x->ch[d^]=y->ch[d];
if(y->ch[d]!=null)y->ch[d]->p=x;
y->p=x->p;
if(!isroot(x))x->p->ch[dir(x)]=y;
y->ch[d]=x;
x->p=y;
x->refresh();
y->refresh();
}

水管局长数据加强版

(附一个bzoj上本题的链接)

只有删边的动态MST,时光倒流之后就转成了只有加边的动态MST,仍然LCT维护。

话说初始MST一开始我是直接用LCT构建的,后来一看怎么我跑得这么慢才发现大家都是用的Kruskal……然后写了一发Prim,发现仍然很慢……= =

直接LCT:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x)))
#define dir(x) ((int)((x)==(x)->p->ch[1]))
using namespace std;
const int maxn=;
template<class T>inline void readint(T &x){
static int c=;
x=;
while(c!=EOF&&(c<''||c>''))c=getchar();
if(c==EOF)return;
while(c>=''&&c<=''){
x=(x<<)+(x<<)+(c^);
c=getchar();
}
}
struct node{
int data,mx,pos;
node *ch[],*p;
bool rev;
node(int d=-):data(d),mx(d),pos(-),rev(false){}
void pushdown(){
if(!rev)return;
if(pos!=-)pos^=;
ch[]->rev^=true;
ch[]->rev^=true;
swap(ch[],ch[]);
rev=false;
}
void refresh(){
mx=data;
pos=-;
if(ch[]->mx>mx){
mx=ch[]->mx;
pos=;
}
if(ch[]->mx>mx){
mx=ch[]->mx;
pos=;
}
}
}nodes[maxn<<],*null=nodes,*ptr;
struct A{int tp,x,y,w;}a[maxn<<];
node *newnode(int);
node *access(node*);
void makeroot(node*);
void link(node*,node*);
void cut(node*,node*);
node *getroot(node*);
node *getmax(node*,node*);
void splay(node*);
void rot(node*,int);
int n,m,q,ans[maxn<<];
map<node*,pair<node*,node*> >mp;
map<pair<int,int>,int>e;
int main(){
freopen("tube_strong.in","r",stdin);
freopen("tube_strong.out","w",stdout);
null->ch[]=null->ch[]=null->p=null;
readint(n);
readint(m);
readint(q);
ptr=nodes+n;
for(int i=;i<=n;i++)nodes[i].ch[]=nodes[i].ch[]=nodes[i].p=null;
while(m--){
int x,y,w;
readint(x);
readint(y);
readint(w);
if(x>y)swap(x,y);
e[make_pair(x,y)]=w;
}
m=q;
for(int i=;i<=m;i++){
readint(a[i].tp);
readint(a[i].x);
readint(a[i].y);
if(a[i].x>a[i].y)swap(a[i].x,a[i].y);
if(a[i].tp==){
a[i].w=e[make_pair(a[i].x,a[i].y)];
e.erase(make_pair(a[i].x,a[i].y));
}
}
for(map<pair<int,int>,int>::iterator it=e.begin();it!=e.end();it++){
a[++m].tp=;
a[m].x=it->first.first;
a[m].y=it->first.second;
a[m].w=it->second;
}
for(int i=m;i;i--){
int x=a[i].x,y=a[i].y,w=a[i].w;
if(a[i].tp==)ans[i]=getmax(nodes+x,nodes+y)->data;
else{
node *tmp;
if(getroot(nodes+x)!=getroot(nodes+y)){
tmp=newnode(w);
link(tmp,nodes+x);
link(tmp,nodes+y);
mp[tmp]=make_pair(nodes+x,nodes+y);
}
else{
tmp=getmax(nodes+x,nodes+y);
if(tmp->data>w){
cut(tmp,mp[tmp].first);
cut(tmp,mp[tmp].second);
tmp->data=w;
link(tmp,nodes+x);
link(tmp,nodes+y);
mp[tmp]=make_pair(nodes+x,nodes+y);
}
}
}
}
for(int i=;i<=m;i++)if(a[i].tp==)printf("%d\n",ans[i]);
return ;
}
node *newnode(int d){
*++ptr=node(d);
ptr->ch[]=ptr->ch[]=ptr->p=null;
return ptr;
}
node *access(node *x){
node *y=null;
while(x!=null){
splay(x);
x->ch[]=y;
(y=x)->refresh();
x=x->p;
}
return y;
}
void makeroot(node *x){
access(x);
splay(x);
x->rev^=true;
}
void link(node *x,node *y){
makeroot(x);
x->p=y;
}
void cut(node *x,node *y){
makeroot(x);
access(y);
splay(y);
y->ch[]=null;
x->p=null;
y->refresh();
}
node *getroot(node *x){
x=access(x);
while(x->pushdown(),x->ch[]!=null)x=x->ch[];
splay(x);
return x;
}
node *getmax(node *x,node *y){
makeroot(x);
x=access(y);
while(x->pushdown(),x->pos!=-)x=x->ch[x->pos];
splay(x);
return x;
}
void splay(node *x){
x->pushdown();
while(!isroot(x)){
if(!isroot(x->p))x->p->p->pushdown();
x->p->pushdown();
x->pushdown();
if(isroot(x->p)){
rot(x->p,dir(x)^);
break;
}
if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^);
else rot(x->p,dir(x)^);
rot(x->p,dir(x)^);
}
}
void rot(node *x,int d){
node *y=x->ch[d^];
x->ch[d^]=y->ch[d];
if(y->ch[d]!=null)y->ch[d]->p=x;
y->p=x->p;
if(!isroot(x))x->p->ch[dir(x)]=y;
y->ch[d]=x;
x->p=y;
x->refresh();
y->refresh();
}

Prim:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x)))
#define dir(x) ((int)((x)==(x)->p->ch[1]))
using namespace std;
const int maxn=;
template<class T>inline void readint(T &x){
static int c=;
x=;
while(c!=EOF&&(c<''||c>''))c=getchar();
if(c==EOF)return;
while(c>=''&&c<=''){
x=(x<<)+(x<<)+(c^);
c=getchar();
}
}
struct node{
int data,mx,pos;
node *ch[],*p;
bool rev;
node(int d=-):data(d),mx(d),pos(-),rev(false){}
void pushdown(){
if(!rev)return;
if(pos!=-)pos^=;
ch[]->rev^=true;
ch[]->rev^=true;
swap(ch[],ch[]);
rev=false;
}
void refresh(){
mx=data;
pos=-;
if(ch[]->mx>mx){
mx=ch[]->mx;
pos=;
}
if(ch[]->mx>mx){
mx=ch[]->mx;
pos=;
}
}
}nodes[maxn<<],*null=nodes,*ptr;
struct oper{int tp,x,y,w;}a[maxn];
struct A{
int x,dis;
A(int x,int dis):x(x),dis(dis){}
bool operator<(const A &a)const{return dis>a.dis;}
};
void Prim();
node *newnode(int);
node *access(node*);
void makeroot(node*);
void link(node*,node*);
void cut(node*,node*);
node *getmax(node*,node*);
void splay(node*);
void rot(node*,int);
vector<int>G[maxn],W[maxn];
int dis[maxn],prt[maxn]={};
bool vis[maxn]={false};
int n,m,q,ans[maxn];
map<node*,pair<node*,node*> >mp;
map<pair<int,int>,int>e;
int main(){
freopen("tube_strong.in","r",stdin);
freopen("tube_strong.out","w",stdout);
null->ch[]=null->ch[]=null->p=null;
readint(n);
readint(m);
readint(q);
ptr=nodes+n;
for(int i=;i<=n;i++)nodes[i].ch[]=nodes[i].ch[]=nodes[i].p=null;
while(m--){
int x,y,w;
readint(x);
readint(y);
readint(w);
if(x>y)swap(x,y);
e[make_pair(x,y)]=w;
}
m=q;
for(int i=;i<=m;i++){
readint(a[i].tp);
readint(a[i].x);
readint(a[i].y);
if(a[i].x>a[i].y)swap(a[i].x,a[i].y);
if(a[i].tp==){
a[i].w=e[make_pair(a[i].x,a[i].y)];
e.erase(make_pair(a[i].x,a[i].y));
}
}
for(map<pair<int,int>,int>::iterator it=e.begin();it!=e.end();it++){
G[it->first.first].push_back(it->first.second);
W[it->first.first].push_back(it->second);
G[it->first.second].push_back(it->first.first);
W[it->first.second].push_back(it->second);
}
Prim();
for(int i=m;i;i--){
int x=a[i].x,y=a[i].y,w=a[i].w;
if(a[i].tp==)ans[i]=getmax(nodes+x,nodes+y)->data;
else{
node *tmp=getmax(nodes+x,nodes+y);
if(tmp->data>w){
cut(tmp,mp[tmp].first);
cut(tmp,mp[tmp].second);
tmp->data=w;
link(tmp,nodes+x);
link(tmp,nodes+y);
mp[tmp]=make_pair(nodes+x,nodes+y);
}
}
}
for(int i=;i<=m;i++)if(a[i].tp==)printf("%d\n",ans[i]);
return ;
}
void Prim(){
fill(dis+,dis+n+,0x3f3f3f3f);
priority_queue<A>q;
dis[]=;
q.push(A(,));
while(!q.empty()){
int x=q.top().x;
q.pop();
if(vis[x])continue;
vis[x]=true;
for(int i=;i<(int)G[x].size();i++)if(!vis[G[x][i]]&&dis[G[x][i]]>W[x][i]){
dis[G[x][i]]=W[x][i];
prt[G[x][i]]=x;
q.push(A(G[x][i],W[x][i]));
}
}
for(int i=;i<=n;i++){
node *x=newnode(dis[i]);
x->p=nodes+prt[i];
nodes[i].p=x;
mp[x]=make_pair(nodes+min(prt[i],i),nodes+max(prt[i],i));
}
}
node *newnode(int d){
*++ptr=node(d);
ptr->ch[]=ptr->ch[]=ptr->p=null;
return ptr;
}
node *access(node *x){
node *y=null;
while(x!=null){
splay(x);
x->ch[]=y;
(y=x)->refresh();
x=x->p;
}
return y;
}
void makeroot(node *x){
access(x);
splay(x);
x->rev^=true;
}
void link(node *x,node *y){
makeroot(x);
x->p=y;
}
void cut(node *x,node *y){
makeroot(x);
access(y);
splay(y);
y->ch[]=null;
x->p=null;
y->refresh();
}
node *getmax(node *x,node *y){
makeroot(x);
x=access(y);
while(x->pushdown(),x->pos!=-)x=x->ch[x->pos];
splay(x);
return x;
}
void splay(node *x){
x->pushdown();
while(!isroot(x)){
if(!isroot(x->p))x->p->p->pushdown();
x->p->pushdown();
x->pushdown();
if(isroot(x->p)){
rot(x->p,dir(x)^);
break;
}
if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^);
else rot(x->p,dir(x)^);
rot(x->p,dir(x)^);
}
}
void rot(node *x,int d){
node *y=x->ch[d^];
x->ch[d^]=y->ch[d];
if(y->ch[d]!=null)y->ch[d]->p=x;
y->p=x->p;
if(!isroot(x))x->p->ch[dir(x)]=y;
y->ch[d]=x;
x->p=y;
x->refresh();
y->refresh();
}

话说这两份代码bzoj上都T到死,也是没谁了……

bzoj2001 [Hnoi2010]City 城市建设

这才是真·动态MST……

听说有个算法叫CDQ重构图,然而太神了并不能看懂,于是乎写了一发对时间分治+LCT,常数大如dog,成功被卡掉……

反正各种卡常都过不去,我还是贴没卡常的代码好了……

 /**************************************************************
Problem: 2001
User: hzoier
Language: C++
Result: Time_Limit_Exceed
****************************************************************/ #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x)))
#define dir(x) ((int)((x)==(x)->p->ch[1]))
using namespace std;
const int maxn=,maxm=;
struct node{
int data,mx,pos;
node *ch[],*p;
bool rev;
node(int d=-):data(d),mx(d),pos(-),rev(false){}
void pushdown(){
if(!rev)return;
if(pos!=-)pos^=;
ch[]->rev^=;
ch[]->rev^=;
swap(ch[],ch[]);
rev=false;
}
void refresh(){
mx=data;
pos=-;
if(ch[]->mx>mx){
mx=ch[]->mx;
pos=;
}
if(ch[]->mx>mx){
mx=ch[]->mx;
pos=;
}
}
}nodes[maxn<<],*null=nodes,*ptr=nodes;
struct edge{int x,y,t,w;}e[maxm];
struct A{
node *x,*u,*v;
int w;
A(node *x,node *u,node *v,int w):x(x),u(u),v(v),w(w){}
};
void addedge(int,int,int);
void solve(int,int,int,long long);
node *newnode(int);
node *access(node*);
void makeroot(node*);
void link(node*,node*);
void cut(node*,node*);
node *getmax(node*,node*);
node *getroot(node*);
void splay(node*);
void rot(node*,int);
vector<int>u[maxm<<],v[maxm<<],w[maxm<<];
map<node*,pair<node*,node*> >mp;
int n,m,q,s,t,k,x,y,z;
node *tmp;
int main(){
null->ch[]=null->ch[]=null->p=null;
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=n;i++)newnode(-);
for(int i=;i<n;i++){
tmp=newnode();
link(tmp,nodes+i);
link(tmp,nodes+i+);
mp[tmp]=make_pair(nodes+i,nodes+i+);
}
for(int i=;i<=m;i++){
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
if(e[i].x>e[i].y)swap(e[i].x,e[i].y);
e[i].t=;
}
for(int i=;i<=q;i++){
scanf("%d%d",&k,&z);
x=e[k].x;y=e[k].y;
s=e[k].t;t=i-;
swap(e[k].w,z);
if(t)addedge(,q,);
e[k].t=i;
}
for(int i=;i<=m;i++){
s=e[i].t;t=q;
x=e[i].x;y=e[i].y;z=e[i].w;
addedge(,q,);
}
solve(,q,,(long long)(n-)*);
return ;
}
void addedge(int l,int r,int rt){
if(s<=l&&t>=r){
u[rt].push_back(x);
v[rt].push_back(y);
w[rt].push_back(z);
return;
}
int mid=(l+r)>>;
if(s<=mid)addedge(l,mid,rt<<);
if(t>mid)addedge(mid+,r,rt<<|);
}
void solve(int l,int r,int rt,long long ans){
vector<A>stk;
for(int i=;i<(int)u[rt].size();i++){
tmp=getmax(nodes+u[rt][i],nodes+v[rt][i]);
if(tmp->data>w[rt][i]){
stk.push_back(A(tmp,mp[tmp].first,mp[tmp].second,tmp->data));
cut(tmp,mp[tmp].first);
cut(tmp,mp[tmp].second);
ans-=tmp->data;
mp[tmp]=make_pair(nodes+u[rt][i],nodes+v[rt][i]);
tmp->data=w[rt][i];
link(tmp,nodes+u[rt][i]);
link(tmp,nodes+v[rt][i]);
ans+=w[rt][i];
}
}
if(l==r)printf("%lld\n",ans);
else{
int mid=(l+r)>>;
solve(l,mid,rt<<,ans);
solve(mid+,r,rt<<|,ans);
}
if(!stk.empty())for(int i=(int)stk.size()-;i>=;i--){
cut(stk[i].x,mp[stk[i].x].first);
cut(stk[i].x,mp[stk[i].x].second);
mp[stk[i].x]=make_pair(stk[i].u,stk[i].v);
stk[i].x->data=stk[i].w;
link(stk[i].x,stk[i].u);
link(stk[i].x,stk[i].v);
}
}
node *newnode(int d){
*++ptr=node(d);
ptr->ch[]=ptr->ch[]=ptr->p=null;
return ptr;
}
node *access(node *x){
node *y=null;
while(x!=null){
splay(x);
x->ch[]=y;
(y=x)->refresh();
x=x->p;
}
return y;
}
void makeroot(node *x){
access(x);
splay(x);
x->rev^=true;
}
void link(node *x,node *y){
makeroot(x);
x->p=y;
}
void cut(node *x,node *y){
makeroot(x);
access(y);
splay(y);
y->ch[]=null;
x->p=null;
y->refresh();
}
node *getmax(node *x,node *y){
makeroot(x);
x=access(y);
while(x->pushdown(),x->pos!=-)x=x->ch[x->pos];
splay(x);
return x;
}
node *getroot(node *x){
x=access(x);
while(x->pushdown(),x->ch[]!=null)x=x->ch[];
splay(x);
return x;
}
void splay(node *x){
x->pushdown();
while(!isroot(x)){
if(!isroot(x->p))x->p->p->pushdown();
x->p->pushdown();
x->pushdown();
if(isroot(x->p)){
rot(x->p,dir(x)^);
break;
}
if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^);
else rot(x->p,dir(x)^);
rot(x->p,dir(x)^);
}
}
void rot(node *x,int d){
node *y=x->ch[d^];
x->ch[d^]=y->ch[d];
if(y->ch[d]!=null)y->ch[d]->p=x;
y->p=x->p;
if(!isroot(x))x->p->ch[dir(x)]=y;
y->ch[d]=x;
x->p=y;
x->refresh();
y->refresh();
}

话说写这题的时候调了半天,最后发现我pushdown的时候忘了交换左右儿子,真是智障……

感觉这几道题还好吧……每道题都是重新打的LCT(虽然调不出来的时候会拿出上一题的代码手动FC……),感觉考试考到的话模板应该是打不错了。

LCT真是累啊……算了我接下来还是专心搞网络流好了……

一堆LCT板子的更多相关文章

  1. BZOJ 2049 SDOI2008 洞穴勘测 LCT板子

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2049 题意概述:给出N个点,一开始不连通,M次操作,删边加边,保证图是一个森林,询问两点连 ...

  2. 沉迷Link-Cut tree无法自拔之:[BZOJ2049]洞穴勘探(蒟蒻的LCT板子)

    来自蒟蒻 \(Hero \_of \_Someone\) 的 \(LCT\) 学习笔记 最近学了一波 \(LCT\) , 于是怒刷 \(LCT\) 合集...... $ $ 学的时候借鉴了 Clove ...

  3. LCT板子

    粘板子: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; c ...

  4. 好的LCT板子和一句话

    typedef long long ll; const int maxn = 400050; struct lct { int ch[maxn][2], fa[maxn], w[maxn]; bool ...

  5. BZOJ 2002 LCT板子题

    思路: LCT啊... (分块也行) 不过YOUSIKI出了一道“弹飞大爷” 就不能用分块水过去了 //By SiriusRen #include <cstdio> #include &l ...

  6. 洛谷P3203 [HNOI2010]弹飞绵羊(LCT,Splay)

    洛谷题目传送门 关于LCT的问题详见我的LCT总结 思路分析 首先分析一下题意.对于每个弹力装置,有且仅有一个位置可以弹到.把这样的一种关系可以视作边. 然后,每个装置一定会往后弹,这不就代表不存在环 ...

  7. bzoj 2049: [Sdoi2008]Cave 洞穴勘测 (LCT)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2049 题面: 2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 1 ...

  8. ☆ [NOI2014] 魔法森林 「LCT动态维护最小生成树」

    题目类型:\(LCT\)动态维护最小生成树 传送门:>Here< 题意:带权无向图,每条边有权值\(a[i],b[i]\).要求一条从\(1\)到\(N\)的路径,使得这条路径上的\(Ma ...

  9. LCT模板(指针版)

    本来是想做THUWC2017的泰勒展开xLCT题的-- 然后觉得数组写很麻烦-- 然后就决定挑战指针版-- 然后写得全是BUG-- 与BUG鏖战三千年后,有了这个指针版LCT板子! #include ...

随机推荐

  1. [LeetCode] Minimum Depth of Binary Tree 二叉树的最小深度

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...

  2. IDEA 中生成 Hibernate 逆向工程实践

    谈起 Hibernate 应该得知道 Gavin King 大叔,他构建了 Hibernate ,并将其捐献给了开源社区. Hibernate 对象关系映射解决方案,为面向对象的领域模型到传统的关系型 ...

  3. UDP通信

    package com.slp; import java.io.IOException; import java.net.DatagramPacket; import java.net.Datagra ...

  4. [HTML5] FileReader对象

    写在前面 前一篇文章介绍了HTML5中的Blob对象(详情戳这里),从中了解到Blob对象只是二进制数据的容器,本身并不能操作二进制,故本篇将对其操作对象FileReader进行介绍. FileRea ...

  5. PDF.NET内存数据库的使用小结

    深蓝医生的PDF.NET数据开发框架提供了一个建议的内存数据库功能,具体的功能介绍我就不多说了,可以看医生的博文<移花接木:当泛型方法遇上抽象类----我的“内存数据库”诞生记>. 我之所 ...

  6. [转]别再抱怨了,国内这么多优秀的Android资源你都知道吗?

    因为一些大家都知道的原因,android很多官方出品的优秀开发资源在国内无法访问. 国内的同行们对此也做出了很多努力,有很多朋友通过各种手段把很多优秀的资源搬运到了国内,为国内android开发者提供 ...

  7. Android 轮换控件

    首先是控件轮换 一.创建主布局 1.用到的控件是 TextSwitcher (文本轮换) 那么其他对应的也就是 ImageSwitcher (图片轮换) <LinearLayout xmlns: ...

  8. 【Android群英传】学习笔记(二)

    在本篇笔记中,小编将记录关于Android Studio使用过程的小技巧 在下面文章为Android Studio 简称As ① 使用Android Studio第一次创建项目等待时间很长? 原因: ...

  9. python gettitle.py

    #!/usr/bin/env python # coding=utf-8 import threading import requests import Queue import sys import ...

  10. theano .dimshuffle

    .dimshuffle 改变输入维度的顺序,返回原始变量的一个view. 输入是一个包含 $[0,1,...,ndim-1]$ 和任意数目的 $'x'$ 的组合: 例如: $('x')$:将标量变成 ...