赛码"BestCoder"杯中国大学生程序设计冠军赛1008(hdu5221)树链剖分点权
来源:互联网 发布:php try catch 编辑:程序博客网 时间:2024/06/08 06:32
Occupation
Accepts: 22
Submissions: 104
Time Limit: 12000/6000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
比赛的时候也没时间看这个题,突然发现好简单的树链剖分
对于操作一,只需要对区间做一个标记,表示他是M的,然后更新属于M的城市的val
对于操作二,跟操作一一样,只不过是把这个城市从M中去除
对于操作三,因为对于以x为根的子树和x在 线段树中是连续的,所以,根据树链剖分预处理出的num(子孙个数,包括这一点)对整个区间进行更新就可以了
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int maxn=100010;int N,M;int val[maxn];int head[maxn],tot,pos;int son[maxn];int num[maxn];int dep[maxn];int fa[maxn];int w[maxn],fw[maxn];int top[maxn];struct node{int v,next;}edge[maxn*2];void init(){tot=pos=0;memset(head,-1,sizeof(head));memset(son,-1,sizeof(son));}void add_edge(int u,int v){edge[tot].v=v;edge[tot].next=head[u];head[u]=tot++;}void dfs1(int u,int f,int depth){fa[u]=f;dep[u]=depth;num[u]=1;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(v==f)continue;dfs1(v,u,depth+1);num[u]+=num[v];if(son[u]==-1||num[son[u]]<num[v])son[u]=v;}}void dfs2(int u,int sp){top[u]=sp;w[u]=++pos;fw[pos]=u;if(son[u]!=-1)dfs2(son[u],sp);for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(v!=fa[u]&&v!=son[u])dfs2(v,v);}}struct IntervalTree{int sum[maxn<<2];int setv[maxn<<2];int active[maxn<<2];void build(int o,int l,int r){sum[o]=setv[o]=active[o]=0;if(l==r){sum[o]=val[fw[l]];return ;}int mid=(l+r)>>1;build(o<<1,l,mid);build(o<<1|1,mid+1,r);sum[o]=sum[o<<1]+sum[o<<1|1];}void update(int o,int l,int r,int q1,int q2,int x){if(q1<=l&&r<=q2){setv[o]=x;if(setv[o])active[o]=sum[o];else active[o]=0;return ;}pushdown(o);int mid=(l+r)>>1;if(q1<=mid)update(o<<1,l,mid,q1,q2,x);if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,x);active[o]=active[o<<1]+active[o<<1|1];}void pushdown(int o){if(setv[o]){setv[o<<1]=setv[o<<1|1]=setv[o];if(setv[o<<1])active[o<<1]=sum[o<<1];else active[o<<1]=0;if(setv[o<<1|1])active[o<<1|1]=sum[o<<1|1];else active[o<<1|1]=0;setv[o]=0;}}}tree;void MChange(int l,int r){int f1=top[l],f2=top[r];while(f1!=f2){if(dep[f1]<dep[f2]){swap(l,r);swap(f1,f2);}tree.update(1,1,N,w[f1],w[l],1);l=fa[f1],f1=top[l];}if(dep[l]>dep[r])swap(l,r);tree.update(1,1,N,w[l],w[r],1);}int main(){int T,u,v;scanf("%d",&T);while(T--){scanf("%d",&N);init();for(int i=1;i<=N;i++)scanf("%d",&val[i]);for(int i=1;i<N;i++){scanf("%d%d",&u,&v);add_edge(u,v);add_edge(v,u);}dfs1(1,0,0);dfs2(1,1);tree.build(1,1,N);scanf("%d",&M);int op,x,y;while(M--){scanf("%d",&op);if(op==1){scanf("%d%d",&x,&y);MChange(x,y);}else if(op==2){scanf("%d",&x);tree.update(1,1,N,w[x],w[x],0);}else{scanf("%d",&x);tree.update(1,1,N,w[x],w[x]+num[x]-1,1);}printf("%d\n",tree.active[1]);}}return 0;}
0 0
- 赛码"BestCoder"杯中国大学生程序设计冠军赛1008(hdu5221)树链剖分点权
- 赛码"BestCoder"杯中国大学生程序设计冠军赛
- 赛码"BestCoder"杯中国大学生程序设计冠军赛hdu5216
- 赛码"BestCoder"杯中国大学生程序设计冠军赛
- "BestCoder"杯中国大学生程序设计冠军赛 HDU 5221 Occupation
- HDU 5214 Movie (赛码"BestCoder"杯中国大学生程序设计冠军赛A题)
- 2016中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2016中国大学生程序设计竞赛
- "巴卡斯杯" 中国大学生程序设计竞赛
- 2016中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- 2017中国大学生程序设计竞赛
- Android 关于android.intent.category.DEFAULT
- 短信模块开发 tpdu格式
- cache和内存的地址映射方式(和组成原理讲的差不多)
- 访问者模式
- 黑马程序员——java基础学习--Collection集合
- 赛码"BestCoder"杯中国大学生程序设计冠军赛1008(hdu5221)树链剖分点权
- TPCC-MySQL基准测试
- java.lang.UnsupportedClassVersionError: Bad version number in .class file异常的处理方法
- Linux平台延时之sleep、usleep、nanosleep、select比较
- pandorabox wifi驱动脚本分析
- Android四大组件之Service
- Hadoop背后的数学问题
- Linux vmstat命令实战详解
- 获取获取手机的型号,系统版本,软件名称,软件版本