[BZOJ1036][ZJOI2008]树的统计Count
来源:互联网 发布:java面试速成 编辑:程序博客网 时间:2024/04/26 03:27
原题地址
树链剖分+线段树
AC code:
#include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std;const int N=30010;const int INF=1<<28;int n,q,tot,c1,c2;int size[N],num[N],bl[N],top[N],last[N];vector<int> G[N];struct nod{ int l,r,s,m; nod *lc,*rc;}pool[N<<2];struct Segtree{ nod *root; void build(nod **p,int L,int R){ *p=&pool[tot++];(*p)->l=L;(*p)->r=R; if(L==R){ (*p)->lc=(*p)->rc=NULL; return ; } int M=(L+R)>>1; build(&(*p)->lc,L,M); build(&(*p)->rc,M+1,R); } void modify(nod *p,int pos,int k){ if(p->l==p->r){ p->s=p->m=k; return ; } int M=(p->l+p->r)>>1; if(pos<=M) modify(p->lc,pos,k); else modify(p->rc,pos,k); p->s=p->lc->s+p->rc->s; p->m=max(p->lc->m,p->rc->m); } int getmax(nod *p,int L,int R){ if(p->l==L&&p->r==R) return p->m; int M=(p->l+p->r)>>1; if(R<=M) return getmax(p->lc,L,R); else if(L>M) return getmax(p->rc,L,R); else return max(getmax(p->lc,L,M),getmax(p->rc,M+1,R)); } int getsum(nod *p,int L,int R){ if(p->l==L&&p->r==R) return p->s; int M=(p->l+p->r)>>1; if(R<=M) return getsum(p->lc,L,R); else if(L>M) return getsum(p->rc,L,R); else return getsum(p->lc,L,M)+getsum(p->rc,M+1,R); }}T;void DFS(int pre,int p){ size[p]=1; for(int i=0;i<G[p].size();i++){ int q=G[p][i]; if(q==pre) continue; DFS(p,q); size[p]+=size[q]; }}void cut(int pre,int p,int number,int belong){ num[p]=number;bl[p]=belong; int q=0,maxs=0; for(int i=0;i<G[p].size();i++){ int next=G[p][i]; if(next==pre) continue; if(size[next]>maxs){ q=G[p][i]; maxs=size[G[p][i]]; } } if(q) cut(p,q,++c1,c2); for(int i=0;i<G[p].size();i++){ int next=G[p][i]; if(next==pre||next==q) continue; else{ top[++c2]=next; last[c2]=p; cut(p,next,++c1,c2); } }}void swap(int *x,int *y){ int t=*x;*x=*y;*y=t;}void qmax(int u,int v){ int ans=-INF; while(bl[u]!=bl[v]){ if(bl[u]>bl[v]) swap(&u,&v); ans=max(ans,T.getmax(T.root,num[top[bl[v]]],num[v])); v=last[bl[v]]; } if(num[u]>num[v]) swap(&u,&v); ans=max(ans,T.getmax(T.root,num[u],num[v])); printf("%d\n",ans);}void qsum(int u,int v){ int ans=0; while(bl[u]!=bl[v]){ if(bl[u]>bl[v]) swap(&u,&v); ans+=T.getsum(T.root,num[top[bl[v]]],num[v]); v=last[bl[v]]; } if(num[u]>num[v]) swap(&u,&v); ans+=T.getsum(T.root,num[u],num[v]); printf("%d\n",ans);}int main(){ scanf("%d",&n); T.build(&T.root,1,n); for(int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } DFS(0,1); top[1]=1; cut(0,1,++c1,++c2); for(int i=1;i<=n;i++){ int t; scanf("%d",&t); T.modify(T.root,num[i],t); } scanf("%d",&q); for(int i=1;i<=q;i++){ int a,b; char ord[11]; scanf("%s%d%d",ord,&a,&b); if(!strcmp(ord,"CHANGE")) T.modify(T.root,num[a],b); else if(!strcmp(ord,"QMAX")) qmax(a,b); else qsum(a,b); } return 0;}
0 0
- [Bzoj1036][ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- 【BZOJ1036】【ZJOI2008】树的统计Count 树链剖分裸题
- 【ZJOI2008】【BZOJ1036】树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count && LCT
- bzoj1036: [ZJOI2008]树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count
- 【bzoj1036】【树链剖分】【ZJOI2008】树的统计Count
- 【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】
- bzoj1036: [ZJOI2008]树的统计Count
- BZOJ1036: [ZJOI2008]树的统计Count (树链剖分)
- bzoj1036: [ZJOI2008]树的统计Count - 树链剖分
- BZOJ1036: [ZJOI2008]树的统计Count
- bzoj1036【ZJOI2008】树的统计Count
- 【树链剖分】[BZOJ1036][ZJOI2008]树的统计Count
- [BZOJ1036] [ZJOI2008]树的统计Count
- [ZJOI2008] [BZOJ1036] 树的统计Count
- PHP中如何通过Web执行C/C++应用程序?
- [BZOJ2152]聪聪可可
- 2015071805 - 所有的都是体验
- Amr and The Large Array
- C++ Primer快速入门之五:实用的模板库
- [BZOJ1036][ZJOI2008]树的统计Count
- PHP,C++,Mysql
- winform中的dateTimePicker控件怎么设置它的默认值为空
- 协同函数的脚本编写
- hibernate3.0 eclipse搭建
- Java基础学习之内部类
- Android 开发有哪些新技术出现?
- HDU 2639 Bone Collector II(01背包 求第k大)
- Mac下Android studio 之NDK配置教程