您的位置:首页 > 其它

【分块】【树上莫队】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终于填完了

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: