习题:观察(dfs序)
题目

思路
方法1
如果你对树剖足够熟悉,那么就有一个\(O(n*log*log)\)的算法,具体分数85'
其相当于从当前节点往上一直打标记,查的时候相当于直接找第一个被打标记的点,
机房某64巨佬表示这不是卡卡就能过
代码1
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
namespace IO
{
void read(int &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(int x)
{
if(x<0)
{
putchar('-');
write(-x);
return;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
}
using namespace IO;
namespace tcs
{
struct node
{
int l,r;
int maxx;
int lazy;
}tre[800000*4+5];
void build(int l,int r,int k)
{
tre[k].l=l;tre[k].r=r;
if(l==r)
return;
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}
void push_down(int k)
{
if(tre[k].lazy==0)
return;
tre[k<<1].maxx=tre[k<<1].maxx+tre[k].lazy;
tre[k<<1|1].maxx=tre[k<<1|1].maxx+tre[k].lazy;
tre[k<<1].lazy+=tre[k].lazy;
tre[k<<1|1].lazy+=tre[k].lazy;
tre[k].lazy=0;
}
void change(int l,int r,int add,int k)
{
if(l>tre[k].r||tre[k].l>r)
return;
if(l<=tre[k].l&&tre[k].r<=r)
{
tre[k].maxx+=add;
tre[k].lazy+=add;
return;
}
push_down(k);
change(l,r,add,k<<1);
change(l,r,add,k<<1|1);
tre[k].maxx=max(tre[k<<1].maxx,tre[k<<1|1].maxx);
}
int findd(int k)
{
if(tre[k].maxx<=0)
return 0;
if(tre[k].l==tre[k].r)
return tre[k].l;
push_down(k);
if(tre[k<<1|1].maxx>=1)
return findd(k<<1|1);
return findd(k<<1);
}
int ask(int l,int r,int k)
{
if(l>tre[k].r||tre[k].l>r)
return 0;
if(l<=tre[k].l&&tre[k].r<=r)
return findd(k);
push_down(k);
int wr=ask(l,r,k<<1|1);
if(wr)
return wr;
else
return ask(l,r,k<<1);
}
int debug(int pos,int k)
{
if(tre[k].l>pos||pos>tre[k].r)
return 0;
if(tre[k].l==tre[k].r)
return tre[k].maxx;
push_down(k);
return debug(pos,k<<1)+debug(pos,k<<1|1);
}
int cnt;
vector<int> g[800005];
int top[800005],dfn[800005],ori[800005];
int dep[800005],wson[800005],siz[800005],fath[800005];
void addedge(int u,int v)
{
g[u].push_back(v);
}
void dfs1(int u,int fa)
{
dep[u]=dep[fa]+1;
siz[u]=1;
fath[u]=fa;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=fa)
{
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[wson[u]])
wson[u]=v;
}
}
}
void dfs2(int u,int top_chain)
{
top[u]=top_chain;
dfn[u]=++cnt;ori[cnt]=u;
if(wson[u])
dfs2(wson[u],top_chain);
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=wson[u]&&v!=fath[u])
dfs2(v,v);
}
}
void init(int n)
{
build(1,n,1);
dfs1(1,0);
dfs2(1,1);
}
void change(int x,int val)
{
int y=1;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
swap(x,y);
change(dfn[top[y]],dfn[y],val,1);
y=fath[top[y]];
}
if(dfn[x]>dfn[y])
swap(x,y);
change(dfn[x],dfn[y],val,1);
}
int ask(int x)
{
int y=1;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
swap(x,y);
int rt=ask(dfn[top[y]],dfn[y],1);
if(rt!=0)
return ori[rt];
y=fath[top[y]];
}
if(dfn[x]>dfn[y])
swap(x,y);
int temp=ask(dfn[x],dfn[y],1);
if(temp==0)
return 0;
return ori[temp];
}
}
using namespace tcs;
int f_abs(int x)
{
return x<0?-x:x;
}
int n,q;
int col[800005];
int main()
{
//ios::sync_with_stdio(false);
freopen("watch.in","r",stdin);
freopen("watch.out","w",stdout);
read(n);read(q);
for(int i=2,u;i<=n;i++)
{
read(u);
addedge(i,u);
addedge(u,i);
}
init(n);
for(int i=1,x;i<=q;i++)
{
read(x);
if(x>0)
{
x=f_abs(x);
if(col[x]==0)
change(x,1);
else
change(x,-1);
col[x]^=1;
/*cout<<"now:\n";
for(int i=1;i<=n;i++)
cout<<debug(i,1)<<' ';
cout<<'\n';*/
}
else
{
x=f_abs(x);
/*cout<<"now:\n";
for(int j=1;j<=n;j++)
cout<<debug(j,1)<<' ';
cout<<'\n';*/
//change(x,1);
/*cout<<"before:\n";
for(int j=1;j<=n;j++)
cout<<debug(j,1)<<' ';
cout<<'\n';*/
write(ask(x));putchar('\n');
//change(x,-1);
/*cout<<"\nafter:\n";
for(int j=1;j<=n;j++)
cout<<debug(j,1)<<' ';
cout<<'\n';*/
}
//cout<<"maxx:"<<tre[1].maxx<<'\n';
//cout<<"debug:"<<debug(1,1)<<'\n';
}
return 0;
}
/*
10 10
6 2 7 9 1 10 5 4 3
-2
1
3
3
-5
8
1
4
-1
-5
5 5
1 1 3 3
1
-1
*/
方法2
考虑实际上如果我们将黑点的dfn从小到大排序,那么可能成为答案的只可能是最小比\(dfn[x]\)大的,或者最大的比\(dfn[x]\)小的
代码2
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<set>
using namespace std;
namespace IO
{
void read(int &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(int x)
{
if(x<0)
{
putchar('-');
write(-x);
return;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
}
using namespace IO;
namespace tcs
{
int cnt;
vector<int> g[800005];
int top[800005],dfn[800005],ori[800005];
int dep[800005],wson[800005],siz[800005],fath[800005];
void addedge(int u,int v)
{
g[u].push_back(v);
}
void dfs1(int u,int fa)
{
dep[u]=dep[fa]+1;
siz[u]=1;
fath[u]=fa;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=fa)
{
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[wson[u]])
wson[u]=v;
}
}
}
void dfs2(int u,int top_chain)
{
top[u]=top_chain;
dfn[u]=++cnt;ori[cnt]=u;
if(wson[u])
dfs2(wson[u],top_chain);
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=wson[u]&&v!=fath[u])
dfs2(v,v);
}
}
void init(int n)
{
dfs1(1,0);
dfs2(1,1);
}
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
swap(x,y);
y=fath[top[y]];
}
if(dep[y]>dep[x])
swap(x,y);
return y;
}
}
using namespace tcs;
int f_abs(int x)
{
return x<0?-x:x;
}
int n,q;
int col[800005];
set<int> s;
int main()
{
//ios::sync_with_stdio(false);
freopen("watch.in","r",stdin);
freopen("watch.out","w",stdout);
read(n);read(q);
for(int i=2,u;i<=n;i++)
{
read(u);
addedge(i,u);
addedge(u,i);
}
init(n);
for(int i=1,x;i<=q;i++)
{
read(x);
if(x>0)
{
x=f_abs(x);
if(col[x]==0)
s.insert(dfn[x]);
else
s.erase(dfn[x]);
col[x]^=1;
}
else
{
x=f_abs(x);
x=dfn[x];
if(s.size()==0)
{
write(0);putchar('\n');
continue;
}
set<int>::iterator t=s.upper_bound(x);
if(t==s.begin())
write(lca(ori[*t],ori[x]));
else if(t==s.end())
{
t--;
write(lca(ori[*t],ori[x]));
}
else
{
set<int>::iterator k=t;
t--;
int lca1=lca(ori[*t],ori[x]);
int lca2=lca(ori[*k],ori[x]);
if(dep[lca1]>dep[lca2])
write(lca1);
else
write(lca2);
}
putchar('\n');
}
}
return 0;
}
/*
10 10
6 2 7 9 1 10 5 4 3
-2
1
3
3
-5
8
1
4
-1
-5
5 5
1 1 3 3
1
-1
*/

浙公网安备 33010602011771号