HDU 5405(树链剖分)
来源:互联网 发布:37传奇霸业羽毛数据 编辑:程序博客网 时间:2024/06/06 20:40
(http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106364#problem/D)
题意:一棵树,点权值,两种操作,1.修改u的权值成w,2.查询u,v,求w[i]*w[j],i,j满足i,j的路径与u,v相交。
解法:先求不相交的。
对于每个节点u , 记录两个值
1. sum[u] u子树w之和。
2. sim( sum[v]^2 ) v是u的轻儿子。
每次修改操作时,对1进行区间更新,更改的2的个数最多为lg(n)个,暴力更改。
每次查询操作,区间查询2,单点查询1,即可完成操作。
总结:感觉这种只记录轻儿子还是很套路的。
//#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <queue>//#include <tr1/unordered_set>#include <tr1/unordered_map>#include <bitset>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1#define inf 1e9#define debug(a) cout << #a" = " << (a) << endl;#define debugarry(a, n) for (int i = 0; i < (n); i++) { cout << #a"[" << i << "] = " << (a)[i] << endl; }#define clr(x, y) memset(x, y, sizeof x)#define ll long long#define ull unsigned long long#define FOR(i,a,b) \ for(i=a;a<b?i<=b:i>=b;a<b?i++:i--)const int maxn = 1e5 + 30;const int mod = 1e9+7;struct sad{ int to,next;}G[maxn<<1];int h[maxn],si;void add(int u,int v){// printf("u %d v %d\n",u,v); G[si].to=v; G[si].next=h[u]; h[u]=si++;}int siz[maxn],dep[maxn];int fa[maxn],son[maxn],top[maxn];void dfs1(int u,int f,int d){ fa[u]=f; dep[u]=d; siz[u]=1; son[u]=-1; for(int i=h[u];~i;i=G[i].next) { int v = G[i].to; if(v^f){ dfs1(v,u,d+1); siz[u]+=siz[v]; if( son[u] == -1 || siz[son[u]] < siz[v] ) son[u] = v; } }}int p[maxn],fp[maxn],pos;void dfs2(int u,int sf){// printf("u %d sf %d son %d\n",u,sf,son[u]); //if( u == 0 ) while(1); top[u] = sf; p[u] = pos++; fp[p[u]]=u; if(son[u]==-1) return ; dfs2(son[u],sf); for(int i=h[u];~i;i=G[i].next) { int v=G[i].to;// debug(v); if(son[u]!=v&&fa[u]!=v) dfs2(v,v); }}int rs[maxn];void upp(int x,int p){ while(x<=pos) { rs[x] = ((rs[x]+p)%mod+mod)%mod; x+=x&-x; }}int get(int x){ int ret = 0; while(x) { ret = (ret+rs[x])%mod; x-=x&-x; } return ret;}int rs2[maxn];void upp2(int x,int p){ while(x<=pos) { rs2[x] = ((rs2[x]+p)%mod+mod)%mod; x+=x&-x; }}int get2(int x){ int ret = 0; while(x) { ret = (ret+rs2[x])%mod; x-=x&-x; } return ret;}int SUM;void Change(int u,int d){ SUM=(SUM+d)%mod; while( u != -1 ) { int f1 = top[u] , f = fa[f1]; int lastsum=get(p[f1]),sum;// printf("u %d f1 %d d %d\n",u,f1,d); upp(p[f1],d); upp(p[u]+1,-d); if( f != -1 ) { sum = get(p[f1]); int t = (ll)sum*sum%mod-(ll)lastsum*lastsum%mod; t = (t%mod+mod)%mod; upp2(p[f],t); } u = f; }}int Query(int u,int v){ int f1 = top[u] , f2 = top[v]; int ret = 0; while(f1^f2) { if( dep[f1] < dep[f2] ) { swap(f1,f2); swap(u,v); } ret = ((ret+get2(p[u])-get2(p[f1]-1))%mod+mod)%mod; int t = get(p[f1]); ret = ((ret-(ll)t*t%mod)%mod+mod)%mod; if( son[u] != -1 ){ int t = get(p[son[u]]); ret = ((ret+(ll)t*t%mod)%mod+mod)%mod; } u = fa[f1]; f1 = top[u]; } if( dep[u] > dep[v] ) swap(u,v); ret = ((ret+get2(p[v])-get2(p[u]-1))%mod+mod)%mod; if( son[v] != -1 ){ int t = get(p[son[v]]); ret = ((ret+(ll)t*t%mod)%mod+mod)%mod; } int t = SUM - get(p[u]); ret = (ret+(ll)t*t%mod)%mod; ret = ( (ll)SUM*SUM%mod - ret ) % mod; return (ret+mod)%mod;}void init(){ clr(h,-1); si=0; pos=1;}int w[maxn];int main(){ //freopen("input.txt","r",stdin); int n,m; while(~scanf("%d%d",&n,&m)) { init(); for(int i=1;i<=n;i++) scanf("%d",&w[i]); int u,v; for(int i=0;i<n-1;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs1(1,-1,1); dfs2(1,1); clr(rs,0); clr(rs2,0); SUM=0; for(int i=1;i<=n;i++) Change(i,w[i]); /*for(int i=1;i<=n;i++) printf("i %d sum %d\n",i,get(p[i]));*/ int a,b,c; for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); if( a == 1 ) { Change(b,(c-w[b]+mod)%mod); w[b] = c; }else printf("%d\n",Query(b,c)); } } return 0;}
0 0
- HDU 5405(树链剖分)
- HDU - 5044(树链剖分)
- HDU 5274(树链剖分)
- HDU 5458(树链剖分)
- HDU 4718(树链剖分)
- HDU 5044 - Tree (树链剖分)
- HDU 5044 Tree(树链剖分)
- HDU 5044 Tree (树链剖分)
- hdu 5221 Occupation(树链剖分)
- HDU 5221 Occupation(树链剖分)
- HDU 5221 Occupation(树链剖分)
- hdu 5044 Tree(树链剖分)
- HDU 5044 Tree (树链剖分)
- hdu-5405
- Hdu 5405 Sometimes Naive 树链剖分+线段树
- hdu 2111(Saving HDU)
- hdu 2109(fighting hdu)
- HDU Saving HDU (贪心)
- 基于Python Django技术构建web系统实践
- Kafka深度解析
- [iOS]编写高质量的Objective-C代码
- Textview的格式化显示
- 24. Swap Nodes in Pairs
- HDU 5405(树链剖分)
- 在Xcode 中如何打包测试版 给测试工程师使用
- MySql “Row size too large (> 8126)”
- MailCore2的使用心得
- 关于某些时候notifyDataSetChanged不运行的问题
- jps命令(Java Virtual Machine Process Status Tool)
- 简单插入排序
- Qt之QHeaderView自定义排序(终极版)
- 数组的循环移位