SPOJ2939 QTREE5(LCT维护子树信息)
2024-10-10 09:34:58
QWQ嘤嘤嘤
此题正规题解应该是边分治??或者是树剖(总之不是LCT)
但是我这里还是把它当成一个LCT题目来做
首先,这个题的重点还是在update上
因为有\(makeroot\)这个操作的存在,所以自然避免不了\(reverse\),而当\(reverse\)之后,会影响到每个点维护的值的时候,就需要同时维护两个相反的数组,在\(reverse\)的时候,直接\(swap\)
对于本题来说,我们对于一个点需要维护一个虚子树的\(maxdis\) (这里需要\(multiset\)来维护,因为access的时候,涉及到修改的问题)
一个到深度最浅的点的\(ans1\),到深度最深的点的\(ans2\),还有一个子\(splay\)的权值和
考虑转移,ans1的转移显然可以由\(ans1[ch[x][0]]\)转移而来(表示左子树内部的路径),其次,他还可以从\(min(fir(s[x]),ans1[ch[x][1]])+val[x]+val[ch[x][0]\)转移而来(表示从右子树或者虚子树开始的一条路径),如果当前点是合法的颜色,那么还可以从当前点开始的一条路径更新\(ans1\),而\(ans2\)直接全部反过来就好
void update(int x)
{
if (!x) return;
sval[x]=sval[ch[x][0]]+sval[ch[x][1]]+val[x];
ans1[x]=min(ans1[ch[x][0]],min(fir(x),ans1[ch[x][1]])+val[x]+sval[ch[x][0]]);
ans2[x]=min(ans2[ch[x][1]],min(fir(x),ans2[ch[x][0]])+val[x]+sval[ch[x][1]]);
//cout<<x<<" "<<ans1[x]<<" "<<ans2[x]<<" "<<sval[x]<<endl;
if (col[x])
{
ans1[x]=min(ans1[x],sval[ch[x][0]]);
ans2[x]=min(ans2[x],sval[ch[x][1]]);
}
//lmn[x]=min(lmn[ls],len[ls]+val[x]+min(w[x],fir(s[x]),lmn[rs]));
//rmn[x]=min(rmn[rs],len[rs]+min(w[x],fir(s[x]),rmn[ls]+val[x]));
}
其他的话,就是一些小细节了,可以直接看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 5e5+1e2;
//const int inf = 1e9;
int lubenwei;
int ch[maxn][3];
int inf;
int fa[maxn],rev[maxn],ans1[maxn],ans2[maxn];
int sval[maxn],val[maxn];
int col[maxn];
int n,m;
multiset<int> s[maxn];
int tot;
int st[maxn];
int son(int x)
{
if (ch[fa[x]][0]==x) return 0;
else return 1;
}
bool notroot(int x)
{
return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
}
void reverse(int x)
{
swap(ans1[x],ans2[x]);
rev[x]^=1;
swap(ch[x][0],ch[x][1]);
}
int fir(int x)
{
//cout<<"ymh"<<endl;
if (s[x].size()>=1) return *(s[x].begin());
else return inf;
}
void update(int x)
{
if (!x) return;
sval[x]=sval[ch[x][0]]+sval[ch[x][1]]+val[x];
ans1[x]=min(ans1[ch[x][0]],min(fir(x),ans1[ch[x][1]])+val[x]+sval[ch[x][0]]);
ans2[x]=min(ans2[ch[x][1]],min(fir(x),ans2[ch[x][0]])+val[x]+sval[ch[x][1]]);
//cout<<x<<" "<<ans1[x]<<" "<<ans2[x]<<" "<<sval[x]<<endl;
if (col[x])
{
ans1[x]=min(ans1[x],sval[ch[x][0]]);
ans2[x]=min(ans2[x],sval[ch[x][1]]);
}
//lmn[x]=min(lmn[ls],len[ls]+val[x]+min(w[x],fir(s[x]),lmn[rs]));
//rmn[x]=min(rmn[rs],len[rs]+min(w[x],fir(s[x]),rmn[ls]+val[x]));
}
void pushdown(int x)
{
if (rev[x])
{
if (ch[x][0]) reverse(ch[x][0]);
if (ch[x][1]) reverse(ch[x][1]);
rev[x]=0;
}
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
int b=son(x),c=son(y);
if (notroot(y)) ch[z][c]=x;
fa[x]=z;
ch[y][b]=ch[x][!b];
fa[ch[x][!b]]=y;
ch[x][!b]=y;
fa[y]=x;
update(y);
update(x);
}
void splay(int x)
{
int y=x,cnt=0;
st[++cnt]=y;
while (notroot(y)) y=fa[y],st[++cnt]=y;
while (cnt) pushdown(st[cnt--]);
while (notroot(x))
{
int y=fa[x],z=fa[y];
int b=son(x),c=son(y);
if (notroot(y))
{
if (b==c) rotate(y);
else rotate(x);
}
rotate(x);
}
///cout<<2<<endl;
update(x);
}
void access(int x)
{
for (int y=0;x;y=x,x=fa[x])
{
splay(x);
// cout<<1;
if (ch[x][1])s[x].insert(ans1[ch[x][1]]);
if (y && s[x].find(ans1[y])!=s[x].end()) s[x].erase(s[x].find(ans1[y]));
ch[x][1]=y;
update(x);
}
// cout<<"wancheng";
}
void makeroot(int x)
{
access(x);//cout<<x<<endl;
splay(x);
reverse(x);
}
int findroot(int x)
{
access(x);
splay(x);
while (ch[x][0])
{
pushdown(x);
x=ch[x][0];
}
return x;
}
void split(int x,int y)
{
makeroot(x);
access(y);
splay(y);
}
void link(int x,int y)
{
split(x,y);
if (findroot(y)!=x)
{
fa[x]=y;
s[y].insert(ans1[x]);
update(y);
}
}
int main()
{
memset(ans1,127/3,sizeof(ans1));
memset(ans2,127/3,sizeof(ans2));
inf = ans1[maxn-3];
n=read();
lubenwei=0;
tot=n;
for (int i=1;i<n;i++)
{
int x=read(),y=read();
val[++tot]=1;
link(x,tot);
link(y,tot);
}
m=read();
makeroot(1);
for (int i=1;i<=m;i++)
{
int opt=read();
int x=read();
if (opt==0)
{
makeroot(x);
col[x]^=1;
if (col[x]==1) lubenwei++;
else lubenwei--;
update(x);
}
if (opt==1)
{
makeroot(x);
if (!lubenwei) cout<<-1<<"\n";
else
if (col[x]) cout<<0<<"\n";
else cout<<ans1[x]<<"\n";
}
// cout<<"6deyanse:"<<col[x]<<endl;
}
return 0;
}
最新文章
- Java 正则表达式匹配模式[贪婪型、勉强型、占有型]
- cain使用教程
- 【LeetCode OJ】Binary Tree Level Order Traversal II
- iOS 进阶 第十七天(0420)
- (转)RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- linux网站推荐
- HTMLayout使用心得
- How to cancel parallel loops in .NET C# z
- Beginning Python From Novice to Professional (4) - 演示样本格式字符串
- layer子层给父层页面元素赋值,以达到向父层页面传值的效果
- [Luogu 2090]数字对
- 转:visualvm监控远程机器上的Java程序
- RabbitMQ使用时注意的一些问题
- C# 高级编程05----常用修饰符
- TJU ACM-ICPC Online Judge—1191 The Worm Turns
- Data Governance
- robot总结
- Docker笔记——搭建私有仓
- 详细注释!二维码条码扫描源码,使用Zxing core2.3
- Dictionary的应用