题解:P4116 Qtree3
what_can_I_do · · 题解
传送门
一个很暴力的算法。
首先打出基础的树链剖分,线段树直接维护一段 dfs 序区间内黑点的个数,如果个数大于
在进行查询的时候,要对查询进行一定的更改。首先要找到第一个黑点可以转化成找到 dfs 序最小的黑点,那么这个点所在的链的链底一定是所有黑点所在的链的链底中 dfs 序最小的。于是在查询
接下来直接暴力跑
CODE:
#include<bits/stdc++.h>
#define lc k<<1
#define rc k<<1|1
#define ll long long
using namespace std;
int n,q;
vector<int> g[100010];
int tot=0,dy[100010];
struct tree
{
int fa,son,dfn,top,size,h;
}tr[100010];
int xds[400010];
int a[100010];
inline void dfs1(int k)
{
tr[k].size=1;
for(register int i=0;i<g[k].size();i++)
{
int x=g[k][i];
if(x==tr[k].fa) continue;
tr[x].fa=k,tr[x].h=tr[k].h+1,dfs1(x),tr[k].size+=tr[x].size;
if(!tr[k].son) tr[k].son=x;
else if(tr[tr[k].son].size<tr[x].size) tr[k].son=x;
}
}
inline void dfs2(int k,int tp)
{
tr[k].top=tp,tot++,tr[k].dfn=tot,dy[tot]=k;
if(!tr[k].son) return;
dfs2(tr[k].son,tp);
for(register int i=0;i<g[k].size();i++)
{
int x=g[k][i];
if(x==tr[k].fa) continue;
if(x!=tr[k].son) dfs2(x,x);
}
}
inline void change(int l,int r,int pos,int k)
{
if(l==r)
{
xds[k]^=1;
return;
}
int mid=(l+r)>>1;
if(pos<=mid) change(l,mid,pos,lc);
else change(mid+1,r,pos,rc);
xds[k]=xds[lc]+xds[rc];
}
inline int query(int l,int r,int ql,int qr,int k)
{
if(ql<=l&&r<=qr) return xds[k];
int sum=0,mid=(l+r)>>1;
if(ql<=mid) sum+=query(l,mid,ql,qr,lc);
if(mid<qr) sum+=query(mid+1,r,ql,qr,rc);
return sum;
}
inline int qulca(int x)
{
int sum=n+1;
while(1)
{
int tx=tr[x].top;
if(tx==1) break;
if(query(1,n,tr[tx].dfn,tr[x].dfn,1)) sum=min(sum,tr[x].dfn);
x=tr[tx].fa;
}
if(query(1,n,1,tr[x].dfn,1)) sum=min(sum,tr[x].dfn);
if(sum==n+1) return -1;
sum=dy[sum];
int block=sqrt(n);
int l=tr[tr[sum].top].dfn,r=tr[sum].dfn;
if(l+block-1>=r)
for(register int i=l;i<=r;i++)
if(a[dy[i]])
return dy[i];
while(l+block-1<r)
{
if(query(1,n,l,l+block-1,1))
for(register int i=l;i<=l+block-1;i++)
if(a[dy[i]])
return dy[i];
l+=block;
}
for(register int i=l;i<=r;i++)
if(a[dy[i]])
return dy[i];
return -1;
}
int main()
{
scanf("%d%d",&n,&q);
for(register int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v),g[v].push_back(u);
}
dfs1(1),dfs2(1,1);
while(q--)
{
int op,x;
scanf("%d%d",&op,&x);
if(!op) change(1,n,tr[x].dfn,1),a[x]^=1;
if(op) printf("%d\n",qulca(x));
}
return 0;
}