【bzoj4999】This Problem Is Too Simple!
来源:互联网 发布:网络流行歌曲2016 编辑:程序博客网 时间:2024/05/16 02:18
【bzoj4999】This Problem Is Too Simple!
题意
给你一颗树,每个节点有个初始值
Wi
现在支持以下两种操作:
1.Cix,0≤x<231) 表示将Wi 改为x
2.Qijx,0≤x<231 表示询问i节点到j节点的路径上有多少个W 为x的节点
解法
树链剖分:
本题的关键在于2操作,只要解决了2操作,就能够想出对应的1操作的方法
点的数目是105 ,操作的次数有5∗105 ,所以不同的权值最多有6∗105 个,可以考虑进行线段树动态加点,对于每一个权值构建一颗线段树。为了方便的表示权值,可以使用map 给每一个权值一个编号
对于每一次1操作,首先在原本的Wi 的线段树进行单点修改:在dfni 处减1,然后在之后的x 的线段树上进行单点修改:在dfni 处+1(当然,一开始给的Wi,i∈【1,n】 要先加进去)
对于2操作,那只需要套用树链剖分路径查询的板子即可,只不过是在x 的线段树上进行查询
复杂度
O(
nlog2n )
代码
#include<iostream>#include<cstdlib>#include<cstdio>#include<cmath>#include<map>#define ls lson[k],l,mid#define rs rson[k],mid+1,r#define Rint register int#define Lint long long intusing namespace std;const int MAXN=1000010;struct node{ int next,to;}t[MAXN];int head[MAXN],num;int lson[MAXN*4],rson[MAXN*4];int dep[MAXN],rt[MAXN*2];int siz[MAXN],son[MAXN];int top[MAXN],dfn[MAXN];int w[MAXN],f[MAXN];int sum[MAXN*4];int n,q,cnt,L;int _cnt,tot;int ans;map<int,int> id;void add(int u,int v){ t[++num]=(node){ head[u],v }; head[u]=num;}void Tarjan(int k){ siz[k]=1; for(int i=head[k],x; i ;i=t[i].next) { x=t[i].to; if( x==f[k] ) continue ; dep[x]=dep[k]+1,f[x]=k; Tarjan( x ); siz[k]+=siz[x]; if( siz[x]>siz[son[k]] || !son[k] ) son[k]=x; }}void dfs(int k){ dfn[k]=++cnt; if( son[k] ) top[son[k]]=top[k],dfs( son[k] ); for(int i=head[k],x; i ;i=t[i].next) { x=t[i].to; if( x==f[k] || x==son[k] ) continue ; top[x]=x,dfs( x ); }}void update(int &k,int l,int r,int x,int w){ if( !k ) k=++tot; sum[k]+=w; if( l==r ) return ; int mid=(l+r)/2; if( x<=mid ) update( ls,x,w ); else update( rs,x,w );}int query(int k,int l,int r,int L,int R){ if( !k ) return 0; if( l==L && r==R ) return sum[k]; int mid=(l+r)/2; if( R<=mid ) return query( ls,L,R ); else if( L>mid ) return query( rs,L,R ); else return query( ls,L,mid )+query( rs,mid+1,R );}int work(int u,int v,int id){ int ret=0; if( dep[u]<dep[v] ) swap( u,v ); while( top[u]!=top[v] ) { if( dep[top[u]]<dep[top[v]] ) swap( u,v ); ret+=query( id,1,n,dfn[top[u]],dfn[u] ); u=f[top[u]]; } if( dep[u]>dep[v] ) swap( u,v ); ret+=query( id,1,n,dfn[u],dfn[v] ); return ret;}int main(){ int u,v,x; char opt[5]; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<=n-1;i++) { scanf("%d%d",&u,&v); add( u,v ),add( v,u ); } f[1]=dep[1]=1,Tarjan( 1 ); top[1]=1,dfs( 1 ); for(int i=1;i<=n;i++) { if( !id[w[i]] ) id[w[i]]=++_cnt; update( rt[id[w[i]]],1,n,dfn[i],1 ); } while( q-- ) { scanf("%s",opt); if( opt[0]=='C' ) { scanf("%d%d",&u,&x); update( rt[id[w[u]]],1,n,dfn[u],-1 ); if( !id[x] ) id[x]=++_cnt; update( rt[id[x]],1,n,dfn[u],1 ); w[u]=x; } else { scanf("%d%d%d",&u,&v,&x); if( !id[x] ) ans=0; else ans=work( u,v,rt[id[x]] ); printf("%d\n",ans); } } return 0;}
阅读全文
0 0
- 【bzoj4999】This Problem Is Too Simple!
- bzoj4999 This Problem Is Too Simple!(树链剖分+动态开点线段树)
- 4999: This Problem Is Too Simple!
- bzoj 4999: This Problem Is Too Simple!
- bzoj 4999: This Problem Is Too Simple!
- BZOJ 4999: This Problem Is Too Simple!
- 4999: This Problem Is Too Simple!
- [BZOJ]4999: This Problem Is Too Simple! 树链剖分
- bzoj 4999: This Problem Is Too Simple! 树链剖分+线段树
- bzoj 4999 This problem is too simple 树链剖分+动态开点线段树
- SVN update problem: This client is too old to work with working copy
- This is the first problem for test. Since all we know the ASCII code, your job is simple: Input numb
- Typically this problem occurs when you are putting in a data that is too long for the column. In t
- This is the first problem
- TecUtilDialogMessageBox("This is the Simple dialog!", MessageBox_Information);
- too young too simple
- too young too simple
- too young too simple
- Python中的向量相加和numpy中的向量相加效率比较
- insertion or merge
- pwnable之brainfuck
- ajax请求后台返回数据data不能遍历
- linux 安装 MySQL ------------python 操作mysql
- 【bzoj4999】This Problem Is Too Simple!
- ajax异步表单提交,并实现文件上传
- 欢迎使用CSDN-markdown编辑器
- include指令与include动作之间的区别
- 高并发解决方案
- double,float浮点型精确运算
- 算法竞赛学习日记(1)——“贪心法”
- NOIP2013 试做总结
- 链表的插入_删除