bzoj4196(树链剖分)

来源:互联网 发布:cydia软件源 sim 编辑:程序博客网 时间:2024/06/05 00:29


不难,但有一些细节

像这种代码量稍微大一些的题,代码比较密集,就要注意

a=a+b;是不是打成

#include<algorithm>#include<cstring>#include<cstdio>#include<cstdlib>#include<cmath>#include<iostream>#define debug(x) cout<<#x<<"="<<x<<endlusing namespace std;const int N=400019;int to[N],pre[N],head[N],tot;//edge int dep[N],fa[N],size[N],son[N],top[N];//树链剖分 int id[N],l[N],r[N],n;//segment treestruct aa{int l,r,sum,set;}a[N*4];void addedge(int x,int y) {to[++tot]=y;pre[tot]=head[x];head[x]=tot;}void dfs1(int u,int depth){dep[u]=depth;int max_size=0;size[u]=1;for (int i=head[u];i;i=pre[i]){dfs1(to[i],depth+1);size[u]+=size[to[i]];if(size[to[i]]>max_size) max_size=size[to[i]],son[u]=to[i];}}void dfs2(int u,int anc){top[u]=anc;l[u]=id[u]=++tot;if (son[u]) dfs2(son[u],anc);for (int i=head[u];i;i=pre[i])if (son[u]!=to[i]) dfs2(to[i],to[i]);r[u]=tot;}void build(int i,int l,int r){a[i].l=l;a[i].r=r;if (l==r) return ;int mid=(l+r)>>1;build(i<<1,l,mid);build(i<<1|1,mid+1,r);}void up(int i){a[i].sum=0;if (a[i<<1].l) a[i].sum+=a[i<<1].sum;if (a[i<<1|1].l) a[i].sum+=a[i<<1|1].sum;//这里刚开始就把=给丢了}void down(int i){if (a[i].set){a[i].set=0;a[i<<1].set=a[i<<1|1].set=1;if (a[i].sum) a[i<<1].sum=a[i<<1].r-a[i<<1].l+1,a[i<<1|1].sum=a[i<<1|1].r-a[i<<1|1].l+1;//这里刚开始直接写成了<span style="font-family: Arial, Helvetica, sans-serif;">a[i<<1|1].r-a[i<<1|1].l+1,没有赋值的情况,然而编译器是不会报错的</span><span style="white-space:pre"></span>//这就要注意不要压行那么严重,注意有没有把赋值或return语句直接写成了一个表达式的情况else a[i<<1].sum=a[i<<1|1].sum=0;}}int find(int i,int l,int r){down(i);if (a[i].l==l&&a[i].r==r) return a[i].sum;if (a[i].l==a[i].r)return 0;int mid=(a[i].l+a[i].r)>>1;if (mid>=r) return find(i<<1,l,r);if (mid<l) return find(i<<1|1,l,r);return find(i<<1,l,mid)+find(i<<1|1,mid+1,r);}void sett(int i,int l,int r,int k){if (a[i].l==l&&a[i].r==r){a[i].set=1;a[i].sum=(a[i].r-a[i].l+1)*k;return;}if (a[i].l==a[i].r) return;int mid=(a[i].l+a[i].r)>>1;if (mid>=r) sett(i<<1,l,r,k);else if (mid<l) sett(i<<1|1,l,r,k);else sett(i<<1,l,mid,k),sett(i<<1|1,mid+1,r,k);up(i);}void install(int x){int ans=0,y=x;while (x!=-1)//把根结点的父亲设为-1,因为如果有根结点的一个轻儿子,那么top就是这个儿子,而他的父亲就是0,x==0了,就会退出,最后没有处理根节点的情况,写题的时候,这样的情况需要多斟酌一下,既然感觉可能有错,就应该好好考虑,不放过每一个可能出错的地方{ans+=find(1,id[top[x]],id[x]);x=fa[top[x]];}printf("%d\n",dep[y]-ans);x=y;while (x!=-1){sett(1,id[top[x]],id[x],1);x=fa[top[x]];}}void uninstall(int x){int ans=find(1,l[x],r[x]);printf("%d\n",ans);sett(1,l[x],r[x],0);}int main(){scanf("%d",&n);fa[0]=-1;for (int i=1;i<n;i++){scanf("%d",&fa[i]);addedge(fa[i],i);}tot=0;dfs1(0,1);dfs2(0,0);build(1,1,tot);int q,x;char c[20];scanf("%d",&q);while (q--){scanf("%s%d",c,&x);if (c[0]=='i') install(x);else uninstall(x);}return 0;}


0 0
原创粉丝点击