想不到自己才过了几天又想写一篇,今天带来的依旧是水题
emm其实就是道树链剖分的模拟题。
传送门:https://www.luogu.org/problemnew/show/P2146
因为只有0没依靠软件,且不会出现环,那么显然依赖关系可以把软件们连成一棵以0为根节点的树。
所以:
因此我只用在树上维护一个线段树记录有多少个节点状态为下载,并用总数与上次操作的总数做差就是答案,很显然可以用树链剖分解决。
代码如下:
#include"cstdio"
#include"algorithm"
#define MAXN 100000+10
using namespace std;
struct edge
{
int v,next;
};
inline int read()
{
char ch=getchar();int x=0,f=1;
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
edge eg[(MAXN)<<1];
int sumv[(MAXN)<<2],lazy_tag[(MAXN)<<2],situ[(MAXN)<<2];
int depth[MAXN],top[MAXN],siz[MAXN],sons[MAXN],fa[MAXN],id[MAXN];
int n,m,last=0,tops=0;
int p[MAXN];
int cnt=0;
char inse[11];
void addedge(int u,int v)
{
eg[++tops].v=v;
eg[tops].next=p[u];
p[u]=tops;
}
void maintain(int o,int l,int r)
{
situ[o]=situ[o<<1]&situ[o<<1|1];
if(situ[o]) sumv[o]=r-l+1;
else sumv[o]=sumv[o<<1]+sumv[o<<1|1];
}
void pushdown(int o,int l,int r)
{
int mid=(l+r)>>1;
if(lazy_tag[o]==1)
{
lazy_tag[o<<1]=1,sumv[o<<1]=mid-l+1,situ[o<<1]=1;
lazy_tag[o<<1|1]=1,sumv[o<<1|1]=r-mid,situ[o<<1|1]=1;
}
else
if(lazy_tag[o]==2)
{
lazy_tag[o<<1]=2,sumv[o<<1]=0,situ[o<<1]=0;
lazy_tag[o<<1|1]=2,sumv[o<<1|1]=0,situ[o<<1|1]=0;
}
lazy_tag[o]=0;
}
void change(int o,int x,int y,int l,int r,int v)
{
if(x<=l&&y>=r)
{
lazy_tag[o]=v;
if(v==1)
sumv[o]=r-l+1,situ[o]=1;
else
sumv[o]=0,situ[o]=0;
return ;
}
int mid=(l+r)>>1;
pushdown(o,l,r);
if(mid>=x)
change(o<<1,x,y,l,mid,v);
if(mid<y)
change(o<<1|1,x,y,mid+1,r,v);
maintain(o,l,r);
}
void uninsta(int x)
{
change(1,id[x],id[x]+siz[x]-1,0,n-1,2);
}
void insta(int x,int y)
{
while(top[x]!=top[y])
{
if(depth[top[x]]>depth[top[y]]) swap(x,y);
change(1,id[top[y]],id[y],0,n-1,1);
y=fa[top[y]];
}
if(depth[x]>depth[y]) swap(x,y);
change(1,id[x],id[y],0,n-1,1);
}
void dfs1(int x,int dep,int fath)
{
siz[x]=1;
depth[x]=dep;
fa[x]=fath;
int maxv=0;
for(int i=p[x]; i; i=eg[i].next)
if(eg[i].v!=fath)
{
dfs1(eg[i].v,dep+1,x);
siz[x]+=siz[eg[i].v];
maxv=maxv==0||siz[eg[i].v]>siz[maxv]?eg[i].v:maxv;
}
sons[x]=maxv;
}
void dfs2(int x,int tops)
{
top[x]=tops;
id[x]=cnt++;
if(!sons[x]) return ;
dfs2(sons[x],tops);
for(int i=p[x]; i; i=eg[i].next)
{
int v=eg[i].v;
if(v==fa[x]||v==sons[x]) continue;
dfs2(v,v);
}
}
int main()
{
n=read();
for(int i=1; i<n; i++)
{
int x=read();
addedge(i,x);
addedge(x,i);
}
dfs1(0,1,0);
dfs2(0,0);
m=read();
for(int i=1; i<=m; i++)
{
scanf("%s",inse+1);
int x=read(),ans;
if(inse[1]=='i')
{
insta(0,x);
ans=sumv[1]-last;
last=sumv[1];
}
else
{
uninsta(x);
ans=last-sumv[1];
last=sumv[1];
}
printf("%d\n",ans);
}
return 0;
}
该代码situ数组是可以不建的,但我还是建了导致没有一次过。我van了。
又犯了许多沙茶错误emm/dk/dk/kel/kel。
还有速度似乎有点慢……
上次写得还蛮快的emm,算了就这样结束吧……emm