【分块】【树上莫队】bzoj1086 bzoj3052
2016-03-28 20:11
260 查看
1086
http://vfleaking.blog.163.com/blog/static/174807634201231684436977/
3052
http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
1086
看了一下感觉很神啊。。果然是bzoj第一页里少数AC人数下一千的题,难怪VFK大大说它很有趣呢。。Orz
在这里MARK一下任务先。
回来填坑啦。。VFK的题解实在是太神了于是我去看了bubuko的。。平时看这个网址的题解也很多了
然后这是一道裸的树上分块。。但是AC人数不上一千啊好奇怪 顺便去理解了一下【B,3B】的问题,还是很好想明白的>_<
大概就是一个栈底的思想维护一下,这个草稿纸上手动写写画画就知道了。
根据这道题,每个块的root都能够到达这个块的所有点,实现也很方便。bubuko跑了24ms,我小号4ms,大号8ms,嘻嘻^_^
3052糖果公园
这是orzliyicheng都还没过的一题,而且还是200ms权限题。。QAQ
开始填坑。
这几天静心一点啊。。退QQ保平安。至少坚持到round2吧
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define ll long long #define N 202020 using namespace std; int c1=0,c2=0; int B,nB,flag ,C ,num ,belong ,n,m,Q,top=0,q ,head ,next ,vet ,dep ,tim=0,edgenum=0; int bin[30],pre ,dfn ,fa[102020][20]; ll res ,ans=0,W ,val ; struct wen{int x,y,c,id;}we ; struct gai{int x,y,pre;}c ; bool operator <(wen a,wen b){ if(belong[a.x]==belong[b.x]&&belong[a.y]==belong[b.y])return a.c<b.c;// if(belong[a.x]==belong[b.x])return belong[a.y]<belong[b.y]; else return belong[a.x]<belong[b.x]; } void add(int u,int v){edgenum++;vet[edgenum]=v;next[edgenum]=head[u];head[u]=edgenum;} int dfs(int u,int ff){//divide the tree int e=head[u];int size=0;dfn[u]=++tim;dep[u]=dep[ff]+1; while(e>0){ int v=vet[e]; if(v!=ff){ fa[v][0]=u;size+=dfs(v,u); if(size>B){ nB++;for(int i=1;i<=size;i++)belong[q[top--]]=nB;//Don't put i into subscript! size=0; } } e=next[e]; }q[++top]=u;return size+1; } int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=16;i>=0;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; for(int i=16;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; if(x!=y)x=fa[x][0];return x; } void reverse(int x){ if(flag[x])ans-=W[num[C[x]]]*val[C[x]],num[C[x]]--;// else num[C[x]]+=1,ans+=W[num[C[x]]]*val[C[x]]; //printf("%d %lld\n",x,ans); flag[x]^=1; } void solve(int x,int y){ while(x!=y){if(dep[x]>dep[y])reverse(x),x=fa[x][0];else reverse(y),y=fa[y][0];} } void change(int x,int y){ if(flag[x]){reverse(x);C[x]=y;reverse(x);//minus plus }else C[x]=y;// don't need to update pre[x] } int main() { bin[0]=1;for(int i=1;i<=20;i++)bin[i]=bin[i-1]*2; scanf("%d%d%d",&n,&m,&Q); B=pow(n,2.0/3)*0.5;//////// for(int i=1;i<=m;i++)scanf("%lld",&val[i]); for(int i=1;i<=n;i++)scanf("%lld",&W[i]); for(int i=1;i<n;i++){ int u,v;scanf("%d%d",&u,&v);add(u,v);add(v,u); } for(int i=1;i<=n;i++)scanf("%d",&C[i]),pre[i]=C[i]; dfs(1,0); for(int i=1;i<=16;i++)for(int j=1;j<=n;j++)fa[j][i]=fa[fa[j][i-1]][i-1]; while(top)belong[q[top--]]=nB; c1=0,c2=0; while(Q--){ int op,x,y; scanf("%d%d%d",&op,&x,&y); if(op==0){//change c1++;c[c1].x=x;c[c1].y=y;c[c1].pre=pre[x];pre[x]=y;//pre[x]--->y }else{ c2++;if(dfn[x]>dfn[y])swap(x,y);//optimize trick we[c2].x=x;we[c2].y=y;we[c2].id=c2;we[c2].c=c1; } } sort(we+1,we+c2+1); for(int i=1;i<=we[1].c;i++)change(c[i].x,c[i].y); solve(we[1].x,we[1].y); int ff=lca(we[1].x,we[1].y); reverse(ff);res[we[1].id]=ans;reverse(ff); for(int i=2;i<=c2;i++){ int prex=we[i-1].x,prey=we[i-1].y; int nowx=we[i].x,nowy=we[i].y; for(int j=we[i-1].c+1;j<=we[i].c;j++)change(c[j].x,c[j].y); for(int j=we[i-1].c;j>we[i].c;j--)change(c[j].x,c[j].pre); solve(prex,nowx);solve(prey,nowy); ff=lca(nowx,nowy); reverse(ff); res[we[i].id]=ans;reverse(ff); } for(int i=1;i<=c2;i++)printf("%lld\n",res[i]); return 0; }update:2017/03/13终于填完了
相关文章推荐
- 表格的编辑,删除,新增操作
- 设计模式之观察者模式
- 项目14-三角形类雏形(2)
- C#的Socket编程基础
- 《Linux内核设计与实现》第十八章读书笔记
- 月光微博客
- leetcode 113. Path Sum II
- HK共享吧解压密码
- 云通信-腾讯云,TLS独立模式公私钥生成
- HK共享吧解压密码
- selenium在远程服务器上的虚拟显示
- Android SwipeRefreshLayout 下拉刷新组件的使用
- 设计模式--单例模式
- React-Native 之Android应用开发踩坑纪 (一)————windows环境下配置
- 缺失值处理方法
- 滴滴出行iOS客户端架构演进之路
- 时间类2
- 实现ViewPager懒加载的三种方法
- Leetcode 112. Path Sum
- POJ 2752 Seek the Name, Seek the Fame(next数组的应用)