hdu3966(数链剖分+线段树区间更新)
来源:互联网 发布:阿里云pc 编辑:程序博客网 时间:2024/06/07 11:07
线段树区间更新得通过新映射的区间进行更新。
PS:当初ad数组开小了,wa了好好几次,可惜
#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int> P;#define fi first#define se second#define INF 0x3f3f3f3f#define clr(x,y) memset(x,y,sizeof x)#define PI acos(-1.0)#define ITER set<int>::iteratorconst int Mod = 1e9 + 7;const int maxn = 5e4 + 10;struct Edge{ int to,next;}edge[maxn << 2];int head[maxn],edge_num,top[maxn],fa[maxn],son[maxn],id[maxn],deq[maxn],siz[maxn],num;ll tree[maxn<<2], a[maxn],ad[maxn << 2];void add(int x,int y){ edge[edge_num] = (Edge){y,head[x]}; head[x] = edge_num++;}//第一次搜索找出siz[],son[],deq[],fa[]void dfs1(int rt,int pa,int d){ deq[rt] = d; son[rt] = 0; fa[rt] = pa; siz[rt] = 1; for(int i=head[rt]; i!=-1; i=edge[i].next){ int t = edge[i].to; if(t != fa[rt]){ dfs1(t,rt,d+1); siz[rt] += siz[t]; if(siz[son[rt]] < siz[t]){//如果父节点的son[rt]的iz[]小于子节点的siz[]更新son[] son[rt] = t; } } }}//第二次搜索找到w[],top[]void dfs2(int rt,int tp){ top[rt] = tp; id[rt] = ++num; if(son[rt] != 0) dfs2(son[rt],tp);//如果当前父节点纯在son 那么为了让链在线段树中连续 先对son[]进行搜索,并且重边顶端的点相同。 for(int i=head[rt]; i!=-1; i=edge[i].next){ int t = edge[i].to; if(t != fa[rt] && son[rt] != t){ dfs2(t,t); } }}void update(int x,ll val,int l,int r,int rt){ if(l == r){tree[rt] = val;return ;} int mid = (l + r) >> 1; if(mid >= x) update(x,val,l,mid,rt << 1); else update(x,val,mid + 1,r,rt << 1 | 1); tree[rt] = tree[rt << 1] + tree[rt << 1| 1];}ll query(int L,int R,int l,int r,int rt){ if(l == L && r == R)return tree[rt]; int mid = (l + r) >> 1; if(ad[rt] != 0) { tree[rt << 1] += ad[rt] * (mid - l + 1);tree[rt << 1|1] += ad[rt] * (r - mid); ad[rt << 1] += ad[rt];ad[rt << 1|1] += ad[rt];ad[rt] = 0; } ll ret = 0; if(R <= mid)ret += query(L,R,l,mid,rt << 1); else if(L >= mid + 1)ret += query(L,R,mid + 1,r,rt << 1 | 1 ); else ret += query(L,mid,l,mid,rt << 1),ret += query(mid + 1,R,mid + 1,r,rt << 1|1); return ret;}void update1(int L,int R,ll val,int l,int r,int rt){ if(L == l && R == r) { tree[rt] += 1ll * (R - L + 1) * val; ad[rt] += val;return ; } int mid = (l + r) >> 1; if(ad[rt] != 0) { tree[rt << 1] += ad[rt] * (mid - l + 1);tree[rt << 1|1] += ad[rt] * (r - mid); ad[rt << 1] += ad[rt];ad[rt << 1|1] += ad[rt];ad[rt] = 0; } if(R <= mid)update1(L,R,val,l,mid,rt << 1); else if(L >= mid + 1)update1(L,R,val,mid + 1,r,rt <<1|1); else { update1(L,mid,val,l,mid,rt << 1);update1(mid+1,R,val,mid + 1,r,rt <<1|1); } tree[rt] = tree[rt << 1] + tree[rt << 1|1];}void updates(int u,int v,ll val){ int f1=top[u],f2=top[v]; while(f1!=f2){ if(deq[f1]<deq[f2]){ swap(f1,f2); swap(u,v); } update1(id[f1],id[u],val,1,num,1);// tmp+=query(id[f1],id[u],1,num,1); u=fa[f1];f1=top[u]; } if(deq[u]>deq[v]) swap(u,v); update1(id[u],id[v],val,1,num,1);// tmp+=query(id[u],id[v],1,num,1);// return tmp;}ll solve(int u,int v){ int f1=top[u],f2=top[v]; ll tmp=0; while(f1!=f2){ if(deq[f1]<deq[f2]){ swap(f1,f2); swap(u,v); } tmp+=query(id[f1],id[u],1,num,1); u=fa[f1];f1=top[u]; } if(deq[u]>deq[v]) swap(u,v); tmp+=query(id[u],id[v],1,num,1); return tmp;}void Init(){ clr(head,-1);edge_num = 0;num = 0;clr(tree,0);clr(ad,0);}int main(){ int n,m,k; while( ~ scanf("%d%d%d",&n,&m,&k)) { Init(); for(int i = 1; i <= n;i ++)scanf("%lld",&a[i]); while(m --){int x,y;scanf("%d%d",&x,&y);add(x,y);add(y,x);} dfs1(1,1,1);dfs2(1,1);// for(int i = 1; i <= n; i ++)cout << i << " <_> " << id[i] << endl; for(int i = 1;i <= n; i ++)update(id[i],a[i],1,num,1); while(k --) { char s[4];int x,y,z;scanf("%s",s); if(s[0] == 'I' || s[0] == 'D') { scanf("%d%d%d",&x,&y,&z); updates(x,y,s[0] == 'I' ? z : -z); } else { int x;scanf("%d",&x); printf("%lld\n",solve(x,x)); } } } return 0;}
附上树状数组代码:
#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int> P;#define fi first#define se second#define INF 0x3f3f3f3f#define clr(x,y) memset(x,y,sizeof x)#define PI acos(-1.0)#define ITER set<int>::iteratorconst int Mod = 1e9 + 7;const int maxn = 5e4 + 10;struct Edge{ int to,next;}edge[maxn << 2];int head[maxn],edge_num,top[maxn],fa[maxn],son[maxn],id[maxn],deq[maxn],siz[maxn],num;ll tree[maxn], a[maxn];void add(int x,int y){ edge[edge_num] = (Edge){y,head[x]}; head[x] = edge_num++;}//第一次搜索找出siz[],son[],deq[],fa[]void dfs1(int rt,int pa,int d){ deq[rt] = d; son[rt] = 0; fa[rt] = pa; siz[rt] = 1; for(int i=head[rt]; i!=-1; i=edge[i].next){ int t = edge[i].to; if(t != fa[rt]){ dfs1(t,rt,d+1); siz[rt] += siz[t]; if(siz[son[rt]] < siz[t]){//如果父节点的son[rt]的iz[]小于子节点的siz[]更新son[] son[rt] = t; } } }}//第二次搜索找到w[],top[]void dfs2(int rt,int tp){ top[rt] = tp; id[rt] = ++num; if(son[rt] != 0) dfs2(son[rt],tp);//如果当前父节点纯在son 那么为了让链在线段树中连续 先对son[]进行搜索,并且重边顶端的点相同。 for(int i=head[rt]; i!=-1; i=edge[i].next){ int t = edge[i].to; if(t != fa[rt] && son[rt] != t){ dfs2(t,t); } }}inline int lowbit(int x){return x & (-x);}ll get(int x){ ll ret = 0; for(int i = x; i > 0;i -= lowbit(i))ret += tree[i]; return ret;}void update(int x,ll val){ for(int i = x; i < maxn; i += lowbit(i))tree[i] += val;}void update1(int l,int r,ll val){ update(l,val);update(r + 1,-val);}void updates(int u,int v,ll val){ int f1=top[u],f2=top[v]; while(f1!=f2){ if(deq[f1]<deq[f2]){ swap(f1,f2); swap(u,v); } update1(id[f1],id[u],val);// tmp+=query(id[f1],id[u],1,num,1); u=fa[f1];f1=top[u]; } if(deq[u]>deq[v]) swap(u,v); update1(id[u],id[v],val);// tmp+=query(id[u],id[v],1,num,1);// return tmp;}void Init(){ clr(head,-1);edge_num = 0;num = 0;clr(tree,0);}int main(){ int n,m,k; while( ~ scanf("%d%d%d",&n,&m,&k)) { Init(); for(int i = 1; i <= n;i ++)scanf("%lld",&a[i]); while(m --){int x,y;scanf("%d%d",&x,&y);add(x,y);add(y,x);} dfs1(1,1,1);dfs2(1,1);// for(int i = 1; i <= n; i ++)cout << i << " <-> " << id[i] << endl; for(int i = 1;i <= n; i ++)update(id[i],a[i]),update(id[i] + 1,-a[i]); while(k --) { char s[4];int x,y,z;scanf("%s",s); if(s[0] == 'I' || s[0] == 'D') { scanf("%d%d%d",&x,&y,&z); updates(x,y,s[0] == 'I' ? z : -z); } else { int x;scanf("%d",&x); printf("%lld\n",get(id[x]) ); } } } return 0;}
阅读全文
0 0
- hdu3966(数链剖分+线段树区间更新)
- 树链剖分(线段树区间更新求和(lazy操作)hdu3966)
- 【HDU3966】Aragorn's Story-树链剖分+线段树区间维护
- hdu3966 树链剖分(区间更新和单点求值)
- 线段树(单点更新+区间更新)
- 线段树区间更新
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- 线段树-区间更新
- 线段树区间更新
- 线段树区间更新
- 线段树区间更新
- 区间更新线段树
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- HDU3966-树链剖分(区间更新,点查询)
- 安装kafka
- Python什么情况下会生成pyc文件?
- 顺序表应用4-2:元素位置互换之逆置算法(数据改进)
- 阿里云Redis公网连接的解决办法
- windows 和ubuntu下host文件
- hdu3966(数链剖分+线段树区间更新)
- 站在你身边的每个人都有可能改变世界,阿里云异构计算加速人工智能
- sql server 笔记
- TensorFlow 图像数据预处理及可视化
- 阿里云发布新一代数据库产品POLARDB_跑分领先一线友商
- 在yii框架下使用redis数据库
- 自创漫画图
- iOS11及iPhone X适配
- use_pair