4034: [HAOI2015]T2 树链剖分+线段树
2016-01-20 07:13
316 查看
卧槽一开始建的单向边结果T的停不下来。
傻逼链剖,别人家的省选qwq。
傻逼链剖,别人家的省选qwq。
#include<iostream> #include<cstdio> #define N 100005 #define ll long long using namespace std; int n,m,cnt,dfn,v ,head ,size ,deep ,fa ,in ,out ,belong ; int list[N<<1],next[N<<1]; int l[N<<2],r[N<<2]; ll sum[N<<2],tag[N<<2]; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void insert(int x,int y) { next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; } void dfs1(int x) { size[x]=1; for (int i=head[x];i;i=next[i]) if (list[i]!=fa[x]) { fa[list[i]]=x; deep[list[i]]=deep[x]+1; dfs1(list[i]); size[x]+=size[list[i]]; } } void dfs2(int x,int chain) { in[x]=++dfn; belong[x]=chain; int k=0; for (int i=head[x];i;i=next[i]) if (list[i]!=fa[x]&&size[list[i]]>size[k]) k=list[i]; if (!k) {out[x]=dfn; return;} dfs2(k,chain); for (int i=head[x];i;i=next[i]) if (list[i]!=fa[x]&&list[i]!=k) dfs2(list[i],list[i]); out[x]=dfn; } inline void pushup(int k) { sum[k]=sum[k<<1]+sum[k<<1|1]; } inline void pushdown(int k) { if (l[k]==r[k]||tag[k]==0) return; tag[k<<1]+=tag[k]; tag[k<<1|1]+=tag[k]; sum[k<<1]+=tag[k]*(r[k<<1]-l[k<<1]+1); sum[k<<1|1]+=tag[k]*(r[k<<1|1]-l[k<<1|1]+1); tag[k]=0; } void build(int k,int x,int y) { l[k]=x; r[k]=y; if (l[k]==r[k]) return; int mid=l[k]+r[k]>>1; build(k<<1,x,mid); build(k<<1|1,mid+1,y); pushup(k); } void modify(int k,int x,int y,ll val) { pushdown(k); if (l[k]==x&&r[k]==y) { sum[k]+=(ll)(r[k]-l[k]+1)*val; tag[k]+=val; return; } int mid=l[k]+r[k]>>1; if (y<=mid) modify(k<<1,x,y,val); else if (x>mid) modify(k<<1|1,x,y,val); else modify(k<<1,x,mid,val),modify(k<<1|1,mid+1,y,val); pushup(k); } ll query(int k,int x,int y) { pushdown(k); if (l[k]==x&&r[k]==y) return sum[k]; int mid=l[k]+r[k]>>1; if (y<=mid) return query(k<<1,x,y); else if (x>mid) return query(k<<1|1,x,y); else return query(k<<1,x,mid)+query(k<<1|1,mid+1,y); } inline ll solve_query(int x) { ll ans=0; while (belong[x]!=1) { ans+=query(1,in[belong[x]],in[x]); x=fa[belong[x]]; } ans+=query(1,1,in[x]); return ans; } int main() { n=read(); m=read(); for (int i=1;i<=n;i++) v[i]=read(); for (int i=1;i<n;i++) { int u=read(),v=read(); insert(u,v); insert(v,u); } dfs1(1); dfs2(1,1); build(1,1,n); for (int i=1;i<=n;i++) modify(1,in[i],in[i],v[i]); for (int i=1;i<=m;i++) { int opt=read(),x=read(),a; switch (opt) { case 1: a=read(); modify(1,in[x],in[x],a); break; case 2: a=read(); modify(1,in[x],out[x],a); break; case 3: printf("%lld\n",solve_query(x)); break; } } return 0; }
相关文章推荐
- 问答 | 我适合做软件开发吗?
- G面经prepare: Pattern Match
- Leetcode @ Word Search II
- thiscall仅仅应用于“C++”成员函数(this指针存放于CX寄存器,参数从右到左压)
- C++编译时函数名修饰约定规则(很具体),MFC提供的宏,extern "C"的作用
- BZOJ 3884: 上帝与集合的正确用法|数论
- Linux下的一个快速跳转到上N层目录的简单方法
- stdcall、cdecl、fastcall、thiscall 、naked call的汇编详解
- Leetcode java Word Search2
- 大数据(十一) - Mahout
- Leetcode@word search
- 主席树 Couriers
- 小娜学法(8):什么叫复核?
- [python] Kmeans文本聚类算法+PAC降维+Matplotlib显示聚类图像
- C语言33行代码简单实现Shell
- 一维条形码攻击技术(Badbarcode)
- POJ-2240-Arbitrage-spfa-寻找正权环
- 这些工具可以帮助我们,纯ubuntu下嵌入式进行开发
- 使用UIDataDetectorTypes自动检测电话、网址和邮箱
- UIWebView用法详解及代码分享