COGS 1817. [WC2013]糖果公园

http://www.cogs.pro/cogs/problem/problem.php?pid=1817

★★★☆   输入文件:park.in   输出文件:park.out   简单对比
时间限制:8 s   内存限制:512 MB

【题目描述】

Candyland 有一座糖果公园,公园里不仅有美丽的风景、好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园玩。

糖果公园的结构十分奇特,它由 n 个游览点构成,每个游览点都有一个糖果发放处,我们可以依次将游览点编号为 1 至 n。有 n−1 条双向道路连接着这些游览点,并且整个糖果公园都是连通的,即从任何一个游览点出发都可以通过这些道路到达公园里的所有其它游览点。

糖果公园所发放的糖果种类非常丰富,总共 m 种,它们的编号依次为 1 至 m。每一个糖果发放处都只发放某种特定的糖果,我们用 ci 来表示 i 号游览点的糖果。

来到公园里游玩的游客都不喜欢走回头路,他们总是从某个特定的游览点出发前往另一个特定的游览点,并游览途中的景点,这条路线一定是唯一的。他们经过每个游览点,都可以品尝到一颗对应种类的糖果。

大家对不同类型的糖果的喜爱程度都不尽相同。根据游客们的反馈打分,我们得到了糖果的美味指数,第 i 种糖果的美味指数为 vi。另外,如果一位游客反复地品尝同一种类的糖果,他肯定会觉得有一些腻。根据量化统计,我们得到了游客第 i 次品尝某类糖果的新奇指数 wi,如果一位游客第 i 次品尝第 j 种糖果,那么他的愉悦指数 H 将会增加对应的美味指数与新奇指数的乘积,即 vjwi。这位游客游览公园的愉悦指数最终将是这些乘积的和。

当然,公园中每个糖果发放点所发放的糖果种类不一定是一成不变的。有时,一些糖果点所发放的糖果种类可能会更改(也只会是 m 种中的一种),这样的目的是能够让游客们总是感受到惊喜。

糖果公园的工作人员小 A 接到了一个任务,那就是根据公园最近的数据统计出每位游客游玩公园的愉悦指数。但数学不好的小 A 一看到密密麻麻的数字就觉得头晕,作为小 A 最好的朋友,你决定帮他一把。

【输入格式

第一行包含三个正整数 n,m,q,分别表示游览点个数、糖果种类数和操作次数。

第二行包含 m 个正整数 v1,v2,…,vm。

第三行包含 n 个正整数 w1,w2,…,wn。

第四行到第 n+2 行,每行包含两个正整数 ai,bi,表示这两个游览点之间有路径可以直接到达。

第 n+3 行包含 n 个正整数 c1,c2,…,cn。

接下来 q 行,每行包含三个整数 t,x,y,表示一次操作:

若 t 为 0,则 1≤x≤n,1≤y≤m,表示编号为 x 的游览点发放的糖果类型改为 y;

若 t 为 1,则 1≤x,y≤n,表示对出发点为 x,终止点为 y 的路线询问愉悦指数。

【输出格式

按照输入的先后顺序,对于每个 t 为 1 的操作输出一行,用一个正整数表示答案。

【样例输入】

4 3 5
1 9 2
7 6 5 1
2 3
3 1
3 4
1 2 3 2
1 1 2
1 4 2
0 2 1
1 1 2
1 4 2

【样例输出】

84
131
27
84

【数据范围】

树上带修改莫队

dfs序分块:

#include<cmath>
#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
int n,m,q,siz;
int tasty[N],curious[N],type[N];
int front[N],to[N<<1],nxt[N<<1],tot;
int now,cnt,block[N],sum[N];
int son[N],deep[N],dfn[N],bl[N],fa[N];
long long tmp,ans[N];
bool v[N];
struct QUERY
{int l,r,id,tim;bool operator < (QUERY p)const{if(block[l]!=block[p.l]) return block[l]<block[p.l];if(block[r]!=block[p.r]) return block[r]<block[p.r];return tim<p.tim;}
}e[N];
struct CHANGE
{int pos,be,af;
}g[N];
void read(int &x)
{x=0; char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
}
void out(long long x)
{if(x/10) out(x/10);putchar(x%10+'0');
}
void add(int u,int v)
{to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}
void init()
{read(n); read(m); read(q);siz=sqrt(n);for(int i=1;i<=m;i++) read(tasty[i]);for(int i=1;i<=n;i++) read(curious[i]);int u,v;for(int i=1;i<n;i++){read(u); read(v);add(u,v);}for(int i=1;i<=n;i++) read(type[i]);int w;tot=0;for(int i=1;i<=q;i++){scanf("%d%d%d",&w,&u,&v);if(!w){g[++now].pos=u; g[now].af=v;}else{e[++cnt].l=u; e[cnt].r=v; e[cnt].id=cnt; e[cnt].tim=now;}}
}
void dfs1(int x)
{son[x]++;for(int i=front[x];i;i=nxt[i]){if(to[i]==fa[x]) continue;deep[to[i]]=deep[x]+1;fa[to[i]]=x;dfs1(to[i]);son[x]+=son[to[i]];}
}
void dfs2(int x,int top)
{dfn[x]=++tot;bl[x]=top;block[x]=(tot-1)/siz+1;int y=0;for(int i=front[x];i;i=nxt[i]){if(to[i]==fa[x]) continue;if(son[to[i]]>son[y]) y=to[i];}if(!y) return;dfs2(y,top);for(int i=front[x];i;i=nxt[i]){if(to[i]==fa[x]||to[i]==y) continue;dfs2(to[i],to[i]);}
}
int get_lca(int u,int v)
{while(bl[u]!=bl[v]){if(deep[bl[u]]<deep[bl[v]]) swap(u,v);u=fa[bl[u]];}if(deep[u]>deep[v]) swap(u,v);return u;
}
void point(int x)
{if(v[x])  {long long o=curious[sum[type[x]]--];tmp-=1ll*tasty[type[x]]*o;}else {long long o=curious[++sum[type[x]]];tmp+=1ll*tasty[type[x]]*o;}v[x]^=1;
}
void path(int u,int v)
{while(u!=v){if(deep[u]<deep[v]) point(v),v=fa[v];else point(u),u=fa[u];}
}
void solve()
{int L=1,R=1,lca; now=0;for(int i=1;i<=cnt;i++){while(now<e[i].tim){now++;g[now].be=type[g[now].pos];if(v[g[now].pos]){point(g[now].pos);type[g[now].pos]=g[now].af;point(g[now].pos);}else  type[g[now].pos]=g[now].af;}while(now>e[i].tim){if(v[g[now].pos]){point(g[now].pos);type[g[now].pos]=g[now].be;point(g[now].pos);}else type[g[now].pos]=g[now].be;now--;    }if(dfn[e[i].l]>dfn[e[i].r]) swap(e[i].l,e[i].r);path(L,e[i].l);path(R,e[i].r);lca=get_lca(e[i].l,e[i].r);point(lca);ans[e[i].id]=tmp;point(lca);L=e[i].l; R=e[i].r;//printf("%d %d:",e[i].l,e[i].r);//printf("%I64d\n",tmp);
    }for(int i=1;i<=cnt;i++) out(ans[i]),puts("");
}
int main()
{init();dfs1(1);dfs2(1,1);sort(e+1,e+cnt+1);solve();
}

View Code

树上分块:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<queue>
#include<cmath>
#include<algorithm>
#define inf 1000000000
#define ll long long
using namespace std;
int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
ll ans,res[100005];
int bin[20];
int n,m,Q,ind,cnt,top;
int blo,blonum;
ll V[100005],W[100005],C[100005],pre[100005];
int fa[100005][17];
int last[100005],q[100005],deep[100005],belong[100005],dfn[100005];
int num[100005];
bool vis[100005];
struct edge{int to,next;}e[200005];
struct query{int x,y,t,id;}b[100005];
struct change{int x,y,t,pre;}c[100005];
bool operator<(query a,query b)
{if(belong[a.x]==belong[b.x]&&belong[a.y]==belong[b.y])return a.t<b.t;else if(belong[a.x]==belong[b.x])return belong[a.y]<belong[b.y];else return belong[a.x]<belong[b.x];
}
void insert(int u,int v)
{e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}
int dfs(int x)
{int size=0;dfn[x]=++ind;for(int i=1;i<=16;i++)if(deep[x]>=bin[i])fa[x][i]=fa[fa[x][i-1]][i-1];else break;for(int i=last[x];i;i=e[i].next)if(e[i].to!=fa[x][0]){deep[e[i].to]=deep[x]+1;fa[e[i].to][0]=x;size+=dfs(e[i].to);if(size>=blo){blonum++;for(int k=1;k<=size;k++)belong[q[top--]]=blonum;size=0;}}q[++top]=x;return size+1;
}
int lca(int x,int y)
{if(deep[x]<deep[y])swap(x,y);int t=deep[x]-deep[y];for(int i=0;bin[i]<=t;i++)if(bin[i]&t)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)return x;return fa[x][0];
}
void reverse(int x)
{if(vis[x])ans-=W[num[C[x]]]*V[C[x]],num[C[x]]--;else num[C[x]]++,ans+=W[num[C[x]]]*V[C[x]];vis[x]^=1;
}
void change(int x,int y)
{if(vis[x]){reverse(x);C[x]=y;reverse(x);}else C[x]=y;
}
void solve(int x,int y)
{while(x!=y){if(deep[x]>deep[y])reverse(x),x=fa[x][0];else reverse(y),y=fa[y][0];}
}
int main()
{bin[0]=1;for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1;n=read();m=read();Q=read();blo=pow(n,2.0/3)*0.5;for(int i=1;i<=m;i++)V[i]=read();for(int i=1;i<=n;i++)W[i]=read();for(int i=1;i<n;i++){int u=read(),v=read();insert(u,v);}for(int i=1;i<=n;i++)pre[i]=C[i]=read();dfs(1);while(top)belong[q[top--]]=blonum;int c1=0,c2=0;for(int i=1;i<=Q;i++){int typ=read(),x=read(),y=read();if(!typ){c1++;c[c1].x=x;c[c1].y=y;c[c1].pre=pre[x];pre[x]=y;}else {c2++;if(dfn[x]>dfn[y])swap(x,y);b[c2].x=x;b[c2].y=y;b[c2].id=c2;b[c2].t=c1;}}sort(b+1,b+c2+1);for(int i=1;i<=b[1].t;i++)change(c[i].x,c[i].y);solve(b[1].x,b[1].y);int t=lca(b[1].x,b[1].y);reverse(t);res[b[1].id]=ans;reverse(t);for(int i=2;i<=c2;i++){for(int j=b[i-1].t+1;j<=b[i].t;j++)change(c[j].x,c[j].y);for(int j=b[i-1].t;j>b[i].t;j--)change(c[j].x,c[j].pre);solve(b[i-1].x,b[i].x);solve(b[i-1].y,b[i].y);int t=lca(b[i].x,b[i].y);reverse(t);res[b[i].id]=ans;reverse(t);}for(int i=1;i<=c2;i++)printf("%lld\n",res[i]);return 0;
}

View Code

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/7072367.html

WC2013 糖果公园相关推荐

  1. LG P4074 [WC2013] 糖果公园(带修莫队,树上莫队)

    LG P4074 [WC2013] 糖果公园 Solution 树上带修莫队,主要还是复习带修莫队和树上莫队. 带修莫队: 带修莫队要先对lll分块的序号作为第一关键字,对rrr分块的序号作为第二关键 ...

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

    [题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的 ...

  3. BZOJ.3052.[WC2013]糖果公园(树上莫队 带修改莫队)

    题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...

  4. [WC2013]糖果公园

    Description 题库链接 给你一棵 $n$ 个节点,有 $m$种颜色的树.每个节点上有一个颜色.定义一条树上路径的价值为 $sum_c V_c(\sum_{i=1}^{tim_c}W_i)$ ...

  5. luogu4074-[WC2013]糖果公园

    Description P4074 [WC2013]糖果公园 - 洛谷 | 计算机科学教育新生态 Solution 树上莫队 && 带修莫队. [模板] 各种莫队 代码 #includ ...

  6. UOJ58 【WC2013】糖果公园

    UOJ58 [WC2013]糖果公园 蒟蒻学个树上莫队都要学一晚上 树上莫队是依照dfs序的,将不过在点遍历完所有儿子后还要再进行一次打时间戳. 用这种方法,再特判一下LCA就好了. 网上的大多数方法 ...

  7. uoj#58./bzoj3052 【WC2013】糖果公园 //树上带修改莫队

    uoj#58. [WC2013]糖果公园 题意 有一棵N(<=1e5)个点的树,每个点对应M(<=1e5)种糖果中的一种. 一条路径的权值定义为∑i(Vi∗∑tij=1Wj)\sum_i ...

  8. 【WC2013】糖果公园 树上莫队

    树上莫队,将树分块,以x,y为一二关键字,以时间为第三关键字.暴力修改. #include <iostream> #include <cstdio> #include < ...

  9. P4074-[WC2013]糖果公园【树上带修莫队】

    正题 题目链接:https://www.luogu.com.cn/problem/P4074 题目大意 nnn个点的一颗数,第iii个点有一颗cic_ici​种类的糖. 第iii次获得jjj种类的糖可 ...

  10. YBTOJ洛谷P4074:糖果公园(树上莫队)

    文章目录 解析 update: 代码 所谓树上莫队,就是在树上的莫队 (逃) 传送门 解析 似乎就是树上的这道题 考虑如何转化为序列问题呢? 考虑dfs序 但是又一个问题... 似乎这条链的dfs序不 ...

最新文章

  1. android客户端证书到期了,在Android设备上生成客户端证书
  2. 【持续更新】JAVA面向对象多线程编程的一些tips
  3. SSAS-MDX#001 - MDX 基本结构
  4. javascript入门_JavaScript代理快速入门
  5. PrismJS,一款漂亮的代码高亮工具
  6. 【设计模式】第一章 面向对象六大原则
  7. Linux中级之lvs三个模式的图像补充(nat,dr,tun)
  8. jquery chosen动态设置值
  9. c语言实现按键的抖动与消除,7.3 按键消抖
  10. opensips脚本转换
  11. mysql中文参考手册 晏子_MySQL中文参考手册(目录)
  12. 向量叉积和点积混合运算_向量点积与叉积的意义
  13. java使用poi导出word并且带图片
  14. html 如何关闭自动填充,如何禁止浏览器自动填充
  15. Oracle的Replace函数与translate函数详解与比较
  16. java来电_java串口 来电显示
  17. 中央电教馆虚拟实验服务器,中央电化教育馆虚拟实验教学区域培训会(广州市)召开...
  18. 【LeetCode】【VSCode】在VSCode中使用插件刷题
  19. android 小鸡走动动画,使用Matter.js实现的小鸡掉落动画
  20. 自动控制理论(1):一般概念及数学模型

热门文章

  1. Django打造大型企业官网-项目实战(二)
  2. 什么是restful api
  3. studio2.3app签名打包安装失败,找不到签名证书。
  4. 关于值传递和指针传递
  5. linux查文件被哪些程序占用—fuser和lsof的使用
  6. Asp.net网站如何播放Flv视频
  7. .net zero power toole 破解日志
  8. 案例分享:巧用工具提升无源码系统的性能和稳定性
  9. oracle知识小结二
  10. 羊坊店不眠夜(续集)