[bzoj 3052][wc2013]糖果公园

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3052

[wc2013]糖果公园

Time Limit: 200 Sec  Memory Limit: 512 MB
Submit: 1213  Solved: 609
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

Sample Input

Sample Output

84
131
27
84

树上莫队,把树分块,然后暴力,说起来是挺简单的,然而……

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cmath>
  4 //using namespace std;
  5 const int maxn = 100005;
  6 typedef long long ll;
  7 ll ans,res[100005];
  8 int n,m,q;
  9 ll V[maxn],W[maxn],C[maxn];
 10 int h[maxn],nx[maxn<<1],to[maxn<<1],cnt;
 11 int fa[maxn],dep[maxn],sz[maxn],ch[maxn],top[maxn],num[maxn];
 12 int dfn[maxn],stack[maxn],stack_top,dfs_clock;
 13 int pos[maxn],pos_count,block_size,block_count,pre[maxn];
 14 bool vis[maxn];
 15 struct TAG1{
 16     int x,y,t,id;
 17 }b[maxn];
 18 struct TAG2{
 19     int x,y,t,pre;
 20 }c[maxn];
 21 int read(){
 22     int rt=0,fl=1;char ch=getchar();
 23     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)fl=-1;ch=getchar();}
 24     while(ch>=‘0‘&&ch<=‘9‘){rt=rt*10+ch-‘0‘;ch=getchar();}
 25     return rt*fl;
 26 }
 27 bool operator < (TAG1 a,TAG1 b){
 28     if(pos[a.x]==pos[b.x]&&pos[a.y]==pos[b.y])return a.t<b.t;
 29     else if(pos[a.x]==pos[b.x])return pos[a.y]<pos[b.y];
 30     else return pos[a.x]<pos[b.x];
 31 }
 32 void add_edge(int u,int v){
 33     to[++cnt]=v;nx[cnt]=h[u];h[u]=cnt;
 34     to[++cnt]=u;nx[cnt]=h[v];h[v]=cnt;
 35 }
 36 void dfs1(int x,int pr){
 37     fa[x]=pr;dep[x]=dep[pr]+1;sz[x]=1;
 38     for(int i=h[x];i;i=nx[i]){
 39         if(to[i]==pr)continue;
 40         dfs1(to[i],x);
 41         sz[x]+=sz[to[i]];
 42         if(sz[ch[x]]<sz[to[i]])ch[x]=to[i];
 43     }
 44 }
 45 void dfs2(int x,int tp){
 46     top[x]=tp;
 47     if(ch[x])dfs2(ch[x],tp);
 48     for(int i=h[x];i;i=nx[i]){
 49         if(to[i]==ch[x]||to[i]==fa[x])continue;
 50         dfs2(to[i],to[i]);
 51     }
 52 }
 53 void dfs3(int x,int pr){
 54     dfn[x]=++dfs_clock;
 55     int now=stack_top;
 56     for(int i=h[x];i;i=nx[i]){
 57         if(to[i]==pr)continue;
 58         dfs3(to[i],x);
 59         if(stack_top-now>=block_size){
 60             block_count++;
 61             while(now!=stack_top){
 62                 pos[stack[stack_top--]]=block_count;
 63             }
 64         }
 65     }
 66     stack[++stack_top]=x;
 67 }
 68 int lca(int u,int v){
 69     while(top[u]!=top[v])dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
 70     return dep[u]<dep[v]?u:v;
 71 }
 72 void reverse(int x){
 73     if(vis[x])ans-=W[num[C[x]]]*V[C[x]],num[C[x]]--;
 74     else num[C[x]]++,ans+=W[num[C[x]]]*V[C[x]];
 75     vis[x]^=1;
 76 }
 77 void change(int x,int y){
 78     if(vis[x]){reverse(x);C[x]=y;reverse(x);}
 79     else C[x]=y;
 80 }
 81 void solve(int x,int y){
 82     while(x!=y) {
 83         if(dep[x]>dep[y])reverse(x),x=fa[x];
 84         else reverse(y),y=fa[y];
 85     }
 86 }
 87 int main(){
 88     n=read();m=read();q=read();
 89     block_size = pow(n,2.0/3)*0.5;
 90     for(int i=1;i<=m;i++)V[i]=read();
 91     for(int i=1;i<=n;i++)W[i]=read();
 92     for(int i=1;i<n;i++)add_edge(read(),read());
 93     for(int i=1;i<=n;i++)pre[i]=C[i]=read();
 94     dfs1(1,0);dfs2(1,1);dfs3(1,0);
 95     block_count++;
 96     while(stack_top)pos[stack[stack_top--]]=block_count;
 97 //  for(int i=1;i<=n;i++)printf("%d ",pos[i]);
 98 //  puts("\nfsdfsdds\n");
 99     int c1=0,c2=0;
100     for(int i=1;i<=q;i++)
101     {
102         int typ=read(),x=read(),y=read();
103         if(!typ)
104         {
105             c1++;
106             c[c1].x=x;c[c1].y=y;c[c1].pre=pre[x];pre[x]=y;
107         }
108         else
109         {
110             c2++;
111             if(dfn[x]>dfn[y])std::swap(x,y);
112             b[c2].x=x;b[c2].y=y;b[c2].id=c2;b[c2].t=c1;
113         }
114     }
115     std::sort(b+1,b+c2+1);
116     for(int i=1;i<=b[1].t;i++)
117         change(c[i].x,c[i].y);
118     solve(b[1].x,b[1].y);
119     int t=lca(b[1].x,b[1].y);
120     reverse(t);res[b[1].id]=ans;reverse(t);
121     for(int i=2;i<=c2;i++)
122     {
123         for(int j=b[i-1].t+1;j<=b[i].t;j++)
124             change(c[j].x,c[j].y);
125         for(int j=b[i-1].t;j>b[i].t;j--)
126             change(c[j].x,c[j].pre);
127         solve(b[i-1].x,b[i].x);
128         solve(b[i-1].y,b[i].y);
129         int t=lca(b[i].x,b[i].y);
130         reverse(t);res[b[i].id]=ans;reverse(t);
131     }
132     for(int i=1;i<=c2;i++)
133         printf("%lld\n",res[i]);
134     return 0;
135 }
136 
时间: 2024-08-26 05:41:05

[bzoj 3052][wc2013]糖果公园的相关文章

bzoj 3052: [wc2013]糖果公园(带修改的树上莫队)

3052: [wc2013]糖果公园 Time Limit: 200 Sec  Memory Limit: 512 MB Submit: 892  Solved: 425 [Submit][Status][Discuss] Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT Source [Submit][Status][Discuss] 题解:bzoj 2120 和 bzoj 37

bzoj 3052: [wc2013]糖果公园 带修改莫队

3052: [wc2013]糖果公园 Time Limit: 250 Sec  Memory Limit: 512 MBSubmit: 506  Solved: 189[Submit][Status] Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT 本来这道题想到了莫队算法,但是看到带修改就直接放弃了.结果看题解才发现带修改居然也能用莫队!!!之所以可以这样用,是因为修改的时间复

[BZOJ 3052] [wc2013] 糖果公园 【树上莫队】

题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之后为第三关键字 排序. 我们将块的大小设置在 n^(2/3) ,这样一共有 n^(1/3) 个块.最后算法的总复杂度会是 n^(5/3) . 每一次如何从上一个询问转移来呢? 假设上一个询问是 (lx, ly, lt) ,这次的询问是 (x, y, t) .t 代表是在第 t 次修改操作之后. 首先

BZOJ 3052 [wc2013]糖果公园 树上莫队

题意:链接 方法:莫队上树 解析: 首先先考虑个莫队的算法,树分块 然后怎么做呢? 可以设两个指针么,然后按一定的排序方式移动指针,使复杂度可过. 观察到这道题是100s的,n^2是GG的,但比n^2稍微小一点就不GG了, 所以排序的作用就体现了. 按照左端点所在块为第一关键字,右端点所在块为第二关键字出现时间为第三关键字排序. 一共有n的1/3次方个块,所以所有的询问的左右端点所在的块的取值最多之后n的2/3次方种,对于每一种,对时间的修改最多会从尾改到头,所以又多乘一个q,n,q同阶,所以总

BZOJ 3052 WC2013 糖果公园 带修改树上莫队

题目大意:给定一棵树,每个点有一个颜色,提供两种操作: 1.询问两点间路径上的Σv[a[i]]*w[k],其中a[i]代表这个点的颜色,k表示这个点是这种颜色第k次出现 2.修改某个点的颜色 VfleaKing的题解见 http://vfleaking.blog.163.com/blog/static/174807634201311011201627/ 带修改莫队上树--如果不带修改就正常搞就好了 如果带修改的话,令块的大小为n^(2/3) 将询问排序时第一键值为左端点所在块,第二键值为右端点所

【BZOJ】3052: [wc2013]糖果公园 树分块+待修改莫队算法

[题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的和或修改一个点的糖果ci.n,m,q<=10^5. [算法]树分块+带修改莫队算法 [题解]参考:WC 2013 糖果公园 park 题解 by vfleaking 首先树分块,参考王室联邦的方法.确定块大小为B,一遍DFS可以分成若干大小为[B,3B]的块,性质是块内两点距离至多为B. 定义(x,

【BZOJ】3052: [wc2013]糖果公园

http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]},可以单点修改颜色.(n, m, q<=100000) #include <bits/stdc++.h> using namespace std; const int N=100005, M=100005; typedef long long ll; inline int getint()

WC2013 糖果公园

COGS 1817. [WC2013]糖果公园 http://www.cogs.pro/cogs/problem/problem.php?pid=1817 ★★★☆   输入文件:park.in   输出文件:park.out   简单对比时间限制:8 s   内存限制:512 MB [题目描述] Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园玩. 糖果公园的结构十分奇特,它由 n 个游览点构成,每个游览点

AC日记——[WC2013]糖果公园 cogs 1817

[WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 100005 #define ll long long struct QueryType { ll u,v,t,id;