BZOJ3052: [wc2013]糖果公园

2024-02-25 16:50
文章标签 糖果 公园 wc2013 bzoj3052

本文主要是介绍BZOJ3052: [wc2013]糖果公园,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

$n \leq 100000$的树,每个点有个糖,$m \leq 100000$种糖,每种糖好吃度$V_i$,吃$j$颗$i$糖会得到愉悦值$V_i*W_j$,$q \leq 100000$个操作:修改一个点上的糖;查询某条链上吃糖的愉悦值。

首先看看能不能用啥数据结构维护。麻烦。好上莫队。

树上的莫队,用dfs的入栈+出栈序可以变区间查询,查询$x$和$y$时,分$x$是否是$y$的祖先、$y$是否是$x$的祖先、两个都不是彼此祖先来查。

莫队的主要复杂度在修改,所以修改只要稍微改一点点东西都会快很多。比如我少了个if就快了10秒。好不卡了没意思。

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 //#include<queue>
  6 //#include<time.h>
  7 //#include<complex>
  8 #include<algorithm>
  9 #include<stdlib.h>
 10 using namespace std;
 11 
 12 int n,m,lq,bl,tot,lc;
 13 #define maxn 200011
 14 int V[maxn],W[maxn],cnt[maxn],a[maxn],bel[maxn];
 15 struct Ques{int l,r,t,id,biu;}q[maxn];
 16 bool cmp(const Ques &a,const Ques &b) {return bel[a.l]==bel[b.l]?(bel[a.r]==bel[b.r]?a.t<b.t:a.r<b.r):a.l<b.l;}
 17 struct Modi{int x,a,b;}mo[maxn];
 18 
 19 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2;
 20 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
 21 void insert(int x,int y) {in(x,y); in(y,x);}
 22 
 23 int A[maxn],B[maxn],list[maxn],len,dep[maxn],Log[maxn],rmq[maxn][20],lr=0,idr[maxn];
 24 void dfs(int x,int fa)
 25 {
 26     list[++len]=x; A[x]=len; dep[x]=dep[fa]+1; rmq[++lr][0]=x; idr[x]=lr;
 27     for (int i=first[x];i;i=edge[i].next)
 28     {
 29         Edge &e=edge[i]; if (e.to==fa) continue;
 30         dfs(e.to,x); rmq[++lr][0]=x;
 31     }
 32     list[++len]=x; B[x]=len;
 33 }
 34 void makermq()
 35 {
 36     Log[0]=-1; for (int i=1;i<=lr;i++) Log[i]=Log[i>>1]+1;
 37     for (int j=1;j<=18;j++)
 38         for (int i=1,to=lr-(1<<j)+1;i<=to;i++)
 39             rmq[i][j]=dep[rmq[i][j-1]]<dep[rmq[i+(1<<(j-1))][j-1]]?rmq[i][j-1]:rmq[i+(1<<(j-1))][j-1];
 40 }
 41 int lca(int x,int y)
 42 {
 43     if (idr[x]>idr[y]) x^=y^=x^=y; x=idr[x]; y=idr[y];
 44     int l=Log[y-x+1];
 45     return dep[rmq[x][l]]<dep[rmq[y-(1<<l)+1][l]]?rmq[x][l]:rmq[y-(1<<l)+1][l];
 46 }
 47 
 48 #define LL long long
 49 LL ans[maxn],ss; bool have[maxn];
 50 void modify(int x)
 51 {
 52     if (have[list[x]]) ss-=V[a[list[x]]]*1ll*W[cnt[a[list[x]]]],cnt[a[list[x]]]--;
 53     else cnt[a[list[x]]]++,ss+=V[a[list[x]]]*1ll*W[cnt[a[list[x]]]];
 54     have[list[x]]^=1;
 55 }
 56 void timemodify(int L,int R,int x,int v)
 57 {
 58     if ((L<=A[x] && A[x]<=R)^(L<=B[x] && B[x]<=R)) modify(A[x]),a[x]=v,modify(A[x]);
 59     else a[x]=v;
 60 }
 61 
 62 int main()
 63 {
 64     scanf("%d%d%d",&n,&m,&lq);
 65     bl=2185;
 66     for (int i=1;i<=n*2;i++) bel[i]=(i-1)/bl+1; tot=bel[n*2];
 67     for (int i=1;i<=m;i++) scanf("%d",&V[i]);
 68     for (int i=1;i<=n;i++) scanf("%d",&W[i]);
 69     for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y);
 70     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
 71     dfs(1,0); makermq();
 72     lc=0;
 73     for (int i=1,op,j=0;i<=lq;i++)
 74     {
 75         scanf("%d",&op);
 76         if (op==1)
 77         {
 78             j++; scanf("%d%d",&q[j].l,&q[q[j].id=j].r); q[j].t=lc;
 79             int l=lca(q[j].l,q[j].r);
 80             if (l==q[j].l || l==q[j].r) {int t=q[j].l; q[j].l=min(A[t],A[q[j].r]); q[j].r=max(A[t],A[q[j].r]); q[j].biu=0;}
 81             else
 82             {
 83                 if (A[q[j].l]<A[q[j].r]) q[j].l=B[q[j].l],q[j].r=A[q[j].r];
 84                 else {int t=q[j].l; q[j].l=B[q[j].r]; q[j].r=A[t];}
 85                 q[j].biu=A[l];
 86             }
 87         }
 88         else
 89         {
 90             lc++; scanf("%d%d",&mo[lc].x,&mo[lc].b);
 91             mo[lc].a=a[mo[lc].x]; a[mo[lc].x]=mo[lc].b;
 92         }
 93     }
 94     lq-=lc;
 95     sort(q+1,q+1+lq,cmp);
 96     
 97     int L=1,R=0,T=lc; ss=0;
 98     for (int i=1;i<=lq;i++)
 99     {
100         while (T<q[i].t) T++,timemodify(L,R,mo[T].x,mo[T].b);
101         while (T>q[i].t) timemodify(L,R,mo[T].x,mo[T].a),T--;
102         while (L<q[i].l) modify(L),L++;
103         while (L>q[i].l) L--,modify(L);
104         while (R<q[i].r) R++,modify(R);
105         while (R>q[i].r) modify(R),R--;
106         if (q[i].biu) modify(q[i].biu);
107         ans[q[i].id]=ss;
108         if (q[i].biu) modify(q[i].biu);
109     }
110     for (int i=1;i<=lq;i++) printf("%lld\n",ans[i]);
111     return 0;
112 }
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/8578422.html

这篇关于BZOJ3052: [wc2013]糖果公园的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/746093

相关文章

【最新华为OD机试E卷-支持在线评测】分糖果(100分)-多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线评测,专栏文章质量平均 94 分 最新华为OD机试目录: https://blog.

力扣135-分发糖果(java详细题解)

题目链接:135. 分发糖果 - 力扣(LeetCode) 前情提要: 因为本人最近都来刷贪心类的题目所以该题就默认用贪心方法来做。 贪心方法:局部最优推出全局最优。 如果一个题你觉得可以用局部最优推出全局最优,并且没有反例来反驳的话就可以用贪心来试试。 题目思路: 本题主要就是难在,有俩个维度,当前的孩子不仅要跟左边比,还要跟右边比。 可能我们一开始就想遍历孩子,让当前孩子先跟左边

【NO.15】LeetCode经典150题-135. 分发糖果

文章目录 【NO.15】LeetCode经典150题-135. 分发糖果解题:贪心 【NO.15】LeetCode经典150题-135. 分发糖果 135. 分发糖果 【困难】 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求,给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。

代码随想录算法训练营第二十九天| 134. 加油站 135. 分发糖果 860.柠檬水找零 406.根据身高重建队列

134. 加油站 题目: 在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 给定两个整数数组 gas 和 cost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证

公园智能厕所显示剩余厕位、公厕空气数据、纸巾耗材余量

在现代化的城市公园中,智能厕所的出现为人们带来了全新的体验。它不仅提供了基本的卫生设施,还通过先进的技术手段,实现了厕位状态监测、空气数据监测以及纸巾、洗手液耗材余量的显示,极大地提升了公共厕所的服务质量。 智能厕所的厕位状态监测功能,让使用者在进入厕所前就能清楚地了解到剩余厕位的情况。通过电子显示屏,你可以一目了然地看到哪些厕位正在使用,哪些厕位空闲。这一功能极大地节省了人们寻找厕位的

贪心算法---分发糖果

题目: n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求,给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。 思路:使用两次贪心思想。 第一次从左到右遍历,只比较右边大于左边的情况,如果ratings[i]>ratings[i-1

九度OJ-1122:吃糖果

就是:N阶楼梯上楼问题。

代码随想录算法训练营第31天| 134. 加油站、135. 分发糖果、860.柠檬水找零、 406.根据身高重建队列

134. 加油站 题目链接:134. 加油站 文档讲解:代码随想录 状态:so easy 思路:每次遍历时,如果当前的油量差(currTank)小于0,说明从当前起点无法到达下一个加油站。此时,将下一个加油站设为新的起点,并重置当前油量差(currTank)。最后检查总的油量差(totalTank),如果总的油量差大于等于0,说明存在一个合法的起点,使汽车能绕完整个环形路;否则不存在

代码随想录算法训练营Day31| 134. 加油站 , 135. 分发糖果 ,860.柠檬水找零 , 406.根据身高重建队列

今天的题目真的写的我一肚子气,真的太气了,一道题都写不出来,再听完题解后,还是觉得没有完全理解,果然菜是原罪,我还是太弱了,继续加油吧!来看今天的第一题 134. 加油站:代码随想录 这道题目的意思就是说一个路上有n个加油站,你现在的初始状态下油是0,你可以选择从一个加油站开始,看你是否能绕路行驶一圈,这道题我想到了,将他所给的gas数组减去cost数组,然后来选,但是我不知道的是怎么来

Leetcode 135. 分发糖果(问题分解)

Leetcode 135. 分发糖果 根据描述,可知更多糖果发生在相邻两个孩子的rating更高者中,对于一个孩子来说,左右两侧都视为相邻,即ratings[ i ] > ratings[ i-1 ] 或 ratings[ i ] > ratings[ i+1 ]都会令糖果增加 由此则将问题分解成两个方面,分别考虑ratings大于左侧和ratings大于右侧两种情况 使用nums[ ] 记录