[BZOJ 4196]软件包管理器
转载请注明出处:http://danihao123.is-programmer.com/
终于A了!
在CodeVS,洛谷甚至UOJ上各种A
但是在BZOJ上各种TLE。BZOJ评测姬自带10倍常数?
这题处理安装很简单,一直溯到根。
删除……注意一下树剖的一些神奇性质。
我们都知道同一重链的点在线段树中是连续的,但是DFS在访问完重链之后访问的是什么?
当然是上一个结点的轻儿子了。
所以说一个子树的所有节点在线段树中也是连续的!
所以问题也就迎刃而解了~
下面是喜闻乐见的代码:
/**************************************************************
Problem: 4196
User: danihao123
Language: C++
Result: Accepted
Time:9628 ms
Memory:10884 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cctype>
using namespace std;
int n;
const int maxn=100001;
vector<int> G[maxn];
inline void Add_Edge(int x,int y){
G[x].push_back(y);
return;
}
// 线段树
int sumv[maxn*4],unsumv[maxn*4],setv[maxn*4];
int _sum,ql,qr;
bool d;
void _query(int o,int L,int R){
if(setv[o]>=0){
_sum+=(d?setv[o]:(setv[o]^1))*(min(qr,R)-max(ql,L)+1);
}else{
if(ql<=L && R<=qr){
_sum+=d?sumv[o]:unsumv[o];
}else{
int M=L+(R-L)/2;
if(ql<=M)
_query(o*2,L,M);
if(qr>M)
_query(o*2+1,M+1,R);
}
}
return;
}
void maintain(int o,int L,int R){
if(R>L){
sumv[o]=sumv[o*2]+sumv[o*2+1];
unsumv[o]=unsumv[o*2]+unsumv[o*2+1];
}
if(setv[o]>=0){
sumv[o]=setv[o]*(R-L+1);
unsumv[o]=(setv[o]^1)*(R-L+1);
}
return;
}
void pushdown(int o){
if(setv[o]>=0){
setv[o*2]=setv[o*2+1]=setv[o];
setv[o]=-1;
}
return;
}
int yl,yr,v;
void _change(int o,int L,int R){
int lc=o*2,rc=o*2+1;
if(yl<=L && R<=yr){
setv[o]=v;
}else{
pushdown(o);
int M=L+(R-L)/2;
if(yl<=M)
_change(lc,L,M);
else
maintain(lc,L,M);
if(yr>M)
_change(rc,M+1,R);
else
maintain(rc,M+1,R);
}
maintain(o,L,R);
return;
}
inline int query(int l,int r,bool done){
_sum=0;
ql=l;
qr=r;
d=done;
_query(1,1,n);
return _sum;
}
inline void change(int l,int r,int value){
yl=l;
yr=r;
v=value;
_change(1,1,n);
return;
}
bool vis[maxn];
int son[maxn],fa[maxn],siz[maxn];
void dfs_1(int x,int father){
fa[x]=father;
siz[x]=1;
int max_siz=0,temp;
for(int i=0;i<G[x].size();i++){
temp=G[x][i];
dfs_1(temp,x);
siz[x]+=siz[temp];
if(siz[temp]>max_siz){
max_siz=siz[temp];
son[x]=temp;
}
}
return;
}
int lable=0;
int tid[maxn],top[maxn];
void dfs_2(int x,int a){
vis[x]=true;
tid[x]=++lable;
top[x]=a;
int temp;
if(son[x]>=0)
dfs_2(son[x],a);
else
return;
for(int i=0;i<G[x].size();i++){
temp=G[x][i];
if(!vis[temp]){
dfs_2(temp,temp);
}
}
return;
}
int install(int x){
register int ans=0;
do{
ans+=query(tid[top[x]],tid[x],false);
change(tid[top[x]],tid[x],1);
x=fa[top[x]];
}while(x>=0);
return ans;
}
int uninstall(int x){
register int ans,k=tid[x]+siz[x]-1;
ans=query(tid[x],k,true);
change(tid[x],k,0);
return ans;
}
inline int readint(){
char c=getchar();
register int x=0;
while(!isdigit(c))
c=getchar();
while(isdigit(c)){
x=x*10+c-'0';
c=getchar();
}
return x;
}
int bf[10];
inline void writeint(int x){
register int p=0;
if(x==0){
bf[p++]=0;
}else{
while(x){
bf[p++]=x%10;
x/=10;
}
}
for(register int i=p-1;i>=0;i--)
putchar('0'+bf[i]);
}
int main(){
register int i;
int m,x;
char buf[10];
n=readint();
for(i=1;i<n;i++){
x=readint();
Add_Edge(x,i);
}
memset(sumv,0,sizeof(sumv));
memset(setv,-1,sizeof(setv));
setv[1]=0;
memset(son,-1,sizeof(son));
memset(vis,0,sizeof(vis));
dfs_1(0,-1);
dfs_2(0,0);
scanf("%d",&m);
for(i=0;i<m;i++){
scanf("\n%s",buf);
x=readint();
if(buf[0]=='i')
writeint(install(x));
else
writeint(uninstall(x));
putchar('\n');
}
return 0;
}
评论 (0)