uoj#58. 【WC2013】糖果公园
2016-06-13 12:35
260 查看
寒假里lbn大爷讲离线算法时就讲过了。。。然而现在才明白该怎么做。
这题就是树上带修莫队,带修莫队就是再加一维时间,然后分块size=n^(2/3),时间复杂度O(n^1.67)。树上莫队可以先求出括号序列,若x为y祖先,则两点间的路径为l[x]~l[y],否则就是r[x]~l[y]+lca。没了。。
这题就是树上带修莫队,带修莫队就是再加一维时间,然后分块size=n^(2/3),时间复杂度O(n^1.67)。树上莫队可以先求出括号序列,若x为y祖先,则两点间的路径为l[x]~l[y],否则就是r[x]~l[y]+lca。没了。。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define ll long long #define N 100005 using namespace std; int n,m,q,p,x,y,sz,v ,w ,first ,c ,len; int dep ,size ,fa ,Bson ,top ; int ord[N*2],l ,r ,s,vis ; int cnt,Ti,la ,Hz ,pos[N*2]; ll now,ans ; struct edge{int to,next;}e[N*2]; struct Q{int x,y,z,id,lca;}Qry ; struct T{int x,u,v;}Mdy ; bool cmp(const Q &a,const Q &b) {return pos[a.x]!=pos[b.x]?pos[a.x]<pos[b.x]:(pos[a.y]!=pos[b.y]?pos[a.y]<pos[b.y]:a.z<b.z);} void link(int x,int y) { e[++len]=(edge){y,first[x]};first[x]=len; } void dfs(int x) { l[x]=++s;ord[s]=x; dep[x]=dep[fa[x]]+1;size[x]=1; for (int i=first[x],t;i;i=e[i].next) if ((t=e[i].to)!=fa[x]) { fa[t]=x;dfs(t);size[x]+=size[t]; if (size[t]>size[Bson[x]]) Bson[x]=t; } r[x]=++s;ord[s]=x; } void dfs(int x,int y) { top[x]=y; if (Bson[x]) dfs(Bson[x],y); for (int i=first[x],t;i;i=e[i].next) if ((t=e[i].to)!=fa[x]&&t!=Bson[x]) dfs(t,t); } int lca(int x,int y) { for (;top[x]!=top[y];x=fa[top[x]]) if (dep[top[x]]<dep[top[y]]) swap(x,y); return (dep[x]<dep[y])?x:y; } void add(int x) { if (vis[x]) now-=(ll)v[c[x]]*w[Hz[c[x]]--]; else now+=(ll)v[c[x]]*w[++Hz[c[x]]]; vis[x]^=1; } void make(int x,int y) { if (vis[x]) add(x),c[x]=y,add(x);else c[x]=y; } int main() { scanf("%d%d%d",&n,&m,&q); for (int i=1;i<=m;i++)scanf("%d",&v[i]); for (int i=1;i<=n;i++)scanf("%d",&w[i]); for (int i=1;i<n;i++)scanf("%d%d",&x,&y),link(x,y),link(y,x); for (int i=1;i<=n;i++)scanf("%d",&c[i]),la[i]=c[i]; dfs(1);dfs(1,1);sz=(int)pow(s,2.0/3); for (int i=1;i<=s;i++) pos[i]=(i-1)/sz; for (int i=1;i<=q;i++) { scanf("%d%d%d",&p,&x,&y); if (p) { if (l[x]>l[y]) swap(x,y); int t=lca(x,y); if (x!=t) Qry[++cnt]=(Q){r[x],l[y],Ti,cnt,t}; else Qry[++cnt]=(Q){l[x],l[y],Ti,cnt,0}; } else Mdy[++Ti]=(T){x,la[x],y},la[x]=y; } sort(Qry+1,Qry+cnt+1,cmp); for (int x=1,y=0,z=0,i=1;i<=cnt;i++) { while(z<Qry[i].z) z++,make(Mdy[z].x,Mdy[z].v); while(z>Qry[i].z) make(Mdy[z].x,Mdy[z].u),z--; while(x>Qry[i].x) add(ord[--x]); while(y<Qry[i].y) add(ord[++y]); while(x<Qry[i].x) add(ord[x++]); while(y>Qry[i].y) add(ord[y--]); if (Qry[i].lca) add(Qry[i].lca); ans[Qry[i].id]=now; if (Qry[i].lca) add(Qry[i].lca); } for (int i=1;i<=cnt;i++) printf("%lld\n",ans[i]); return 0; }
相关文章推荐
- java并发编程(十五)--线程间通信中notifyAll造成的早期通知问题
- jq 中each的用法
- NSURLSession的使用
- [leetcode] 357. Count Numbers with Unique Digits 解题报告
- js生成随机数
- 《深入理解java虚拟机》读书笔记-第八章虚拟机字节码执行引擎
- 线程及其实现
- 文章标题
- zk之validation
- Java的反射机制浅谈
- 异常集锦
- 二十世纪最伟大的10大算法
- ID3和C4.5决策树算法总结
- java并发编程(十四)--线程间通信中notify通知的遗漏
- MySQL常用操作
- Java中instanceof
- [Effective JavaScript 笔记]第30条:理解prototype、getPrototypeOf和__ptoto__之间的不同
- OpenMP简介
- Composite(组合模式)
- Insert Interval