The 2020 ICPC Asia Macau Regional Contest J. Jewel Grab(数颜色+链表)

J. Jewel Grab

Tartarus
_Wallace_


转化询问:对于一个询问 [s,k],找到一个最长的区间 [s,t],满足区间中出现次数超过一次的元素,的出现次数减一,的和,不超过 k。

对于该区间[s,t] 区间数颜色:也就是每种颜色只算一个权值求最大和(显然每种颜色都取最大的权值)于是有下面转化:对于所有区间中出现次数超过一次的元素,找出其中权值最大的求和;对其他的元素(仅仅出现一次)直接求和。计算最终结果。


区间数颜色显然要维护一个pre[x]数组表示前一个出现c[x]的位置在哪?

首先我们考虑如何找到区间的端点t,也就是找到[s,t]这个区间。由于k非常小,考虑一次只忽略一个宝石,也就是每次找到第一个 pre[x]>s 的 x 即可,那么由于pre[x]和x都在所考虑区间内部,于是就需要多一次忽略。

显然c[x]就是出现次数超过一次的元素 于是只需要记录mc[c[x]]每次选择最大的。而对于[cur,x)这段区间都是其他的元素(仅仅出现一次)直接区间求和即可计算贡献。


考虑如何修改?

每当修改一个位置的颜色最多会有3个位置的pre[]发生改变:

  • 该位置pre一定改变
  • 原颜色后面位置的pre(可能)改变
  • 新颜色后面位置的pre(可能)改变

可以考虑用一个双链表pre[],nxt[]维护一下。详细参考代码,代码都是抄第一篇博客的。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
template <class T=int> T rd()
{T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg;
}
const int N=200010;int n,m;
int pre[N],last[N],nxt[N];
int c[N];ll v[N],mc[N];
set<int> cp[N];
void prework()
{memset(last,-1,sizeof last);for(int i=n;i>=1;i--){nxt[i]=last[c[i]];last[c[i]]=i;}memset(last,-1,sizeof last);for(int i=1;i<=n;i++) {pre[i]=last[c[i]];last[c[i]]=i;cp[c[i]].insert(i);}
}
struct node
{int l,r;int v;ll s;
}t[N<<2];
void pushup(int u)
{t[u].v=max(t[u<<1].v,t[u<<1|1].v);t[u].s=t[u<<1].s+t[u<<1|1].s;
}
void build(int u,int l,int r)
{t[u]={l,r};if(l==r){t[u].v=pre[l];t[u].s=v[l];return;}int mid=l+r>>1;build(u<<1,l,mid),build(u<<1|1,mid+1,r);pushup(u);
}
void modify(int u,int p)
{if(t[u].l==t[u].r) {t[u].v=pre[p];t[u].s=v[p];return;}int mid=t[u].l+t[u].r>>1;if(p<=mid) modify(u<<1,p);else modify(u<<1|1,p);pushup(u);
}
ll query(int u,int l,int r)
{if(l<=t[u].l&&t[u].r<=r) return t[u].s;int mid=t[u].l+t[u].r>>1;ll v=0;if(l<=mid) v+=query(u<<1,l,r);if(r>mid) v+=query(u<<1|1,l,r);return v;
}
int find(int u,int s,int p)
{if(t[u].l==t[u].r) return t[u].l;int mid=t[u].l+t[u].r>>1;int pos=-1;if(t[u<<1].v>=s&&p<=mid)    pos=find(u<<1,s,p);if(pos!=-1) return pos;if(t[u<<1|1].v>=s)pos=find(u<<1|1,s,p);return pos;
}
int main()
{n=rd(),m=rd();for(int i=1;i<=n;i++) c[i]=rd(),v[i]=rd();prework();build(1,1,n);while(m--){int op=rd();if(op==1){int x=rd(),c0=rd(),v0=rd();cp[c[x]].erase(x);// 最后一次出现的c[x]的位置if(last[c[x]]==x) last[c[x]]=pre[x];v[x]=v0;c[x]=c0;// 删除的修改// 链表的一些删除操作if(nxt[x]!=-1) {if(pre[x]!=-1) {nxt[pre[x]]=nxt[x];pre[nxt[x]]=pre[x];modify(1,nxt[x]);// nxt[x]的pre[]发生改变需要维护}else{pre[nxt[x]]=-1;modify(1,nxt[x]);}}else{if(pre[x]!=-1) nxt[pre[x]]=-1;}// 插入的修改int pos;set<int>::iterator it;it=cp[c0].lower_bound(x);// 插入在末尾if(it==cp[c0].end()){nxt[x]=-1;pre[x]=last[c0];if(pre[x]!=-1) nxt[pre[x]]=x;modify(1,x);}else{pos=*it;if(pre[pos]!=-1) //插入不在开头{nxt[pre[pos]]=x;pre[x]=pre[pos];modify(1,x);}// 插入在开头else{pre[x]=-1;modify(1,x);}nxt[x]=pos;pre[pos]=x;modify(1,pos);}cp[c0].insert(x);last[c0]=max(last[c0],x);}else{int s=rd(),k=rd();vector<int> col;int cur=s;ll ans=0;for(int j=0;j<=k&&cur<=n;j++){int pos=find(1,s,cur);if(pos==-1) {ans+=query(1,cur,n);break;}col.push_back(c[pos]);if(j<k){// 出现一次直接选if(mc[c[pos]]==0) mc[c[pos]]=v[pre[pos]];// 出现第二次考虑与第一次出现的比较if(v[pos]>mc[c[pos]]){ans-=mc[c[pos]];ans+=v[pos];mc[c[pos]]=v[pos];}}ans+=query(1,cur,pos-1);// [cur,pos-1]都是第一次出现cur=pos+1;}printf("%lld\n",ans);for(int u:col) mc[u]=0;}}return 0;
}

太难了吧。。
要加油哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318571.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客题霸 [最大数] C++题解/答案

牛客题霸 [最大数] C题解/答案 题目描述 给定一个数组由一些非负整数组成&#xff0c;现需要将他们进行排列并拼接&#xff0c;使得最后的结果最大&#xff0c;返回值需要是string类型 否则可能会溢出 题解&#xff1a; 将字符串存入vector中然后sort排序&#xff0c;最后将…

模板:割点、桥与双连通

文章目录割点代码桥点双连通分量代码边双连通分量代码割点 和强连通分量十分相似 分为树枝边、前向边和后向边 注意&#xff01; if(x!r&&low[to]>dfn[x]) cut[x]1;这句判断只能在树枝边出现 否则会因为前向边的存在而出错 代码 #include<bits/stdc.h> us…

.NET Core实战项目之CMS 第十章 设计篇-系统开发框架设计

这两天比较忙&#xff0c;周末也在加班&#xff0c;所以更新的就慢了一点&#xff0c;不过没关系&#xff0c;今天我们就进行千呼万唤的系统开发框架的设计。不知道上篇关于架构设计的文章大家有没有阅读&#xff0c;如果阅读后相信一定对架构设计有了更近一部的理解&#xff0…

喝酒、工作与自律

喝酒 自从开始打算品酒之后&#xff0c;家里的小酒数量不断增加&#xff0c;每天晚上喝个15ml&#xff0c;慢慢也能喝出一些区别了。 酱香、清香、浓香的区别还是挺明显的&#xff0c;闻香就能区别出来 浓香里的五粮液特点很明显&#xff0c;闻的时候有粮香&#xff0c;入口后…

51nod1836-战忽局的手段【期望dp,矩阵乘法】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1836 题目大意 nnn个点mmm次随机选择一个点标记&#xff08;可以重复&#xff09;&#xff0c;求最后被标记点的期望个数。 1≤n,m≤10181\leq n,m\leq 10^{18}1≤n,m≤1018 解题思路 额开始拿方案数推了…

分析现有 WPF / Windows Forms 程序能否顺利迁移到 .NET Core 3.0

今年五月的 Build 大会上&#xff0c;微软说 .NET Core 3.0 将带来 WPF / Windows Forms 这些桌面应用的支持。当然&#xff0c;是通过 Windows 兼容包&#xff08;Windows Compatibility Pack&#xff09;实现的。为了提前检查你的程序是否能在未来跑在 .NET Core 3.0 上&…

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明) Stone Games

Stone Games 主席树 Code1 #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N1000010; using lllong long; const ll MAX1000000000ll; int n,a[N],m; struct node {int l,r;ll v; }tree[N*40]; int root[N],c…

路径求和(ybtoj-树形dp)

文章目录题目描述解析代码题目描述 给出一棵带边权的树&#xff0c;求所有至少有一个端点为叶节点的所有简单路径的长度和 解析 换一个角度想 考虑将树分割为AB两部分的一条边会存在于多少条符合条件的路径中&#xff08;也就是边权会考虑多少次&#xff09; 不难发现&#…

51nod1675-序列变换【莫比乌斯反演】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1675 题目大意 给出两个长度为nnn的序列a,ba,ba,b&#xff0c;求有多少对x,yx,yx,y满足 gcd(x,y)1且abxbaygcd(x,y)1且a_{b_x}b_{a_y}gcd(x,y)1且abx​​bay​​ 1≤n≤105,1≤ai,bi≤n1\leq n\leq 10^5…

牛客题霸 [子数组最大乘积] C++题解/答案

牛客题霸 [子数组最大乘积] C题解/答案 题目描述 给定一个double类型的数组arr&#xff0c;其中的元素可正可负可0&#xff0c;返回子数组累乘的最大乘积。 题解&#xff1a; 同时记录最大值和最小值&#xff0c;为什么?因为给的元素是存在负数的&#xff0c;当出现负数时…

ML.NET 0.8特性简介

本周.NET生态圈内的更新源源不断&#xff0c;除了.NET Core 2.2&#xff0c;ASP.NET Core 2.2和Entity Framework Core 2.2之外&#xff0c;ML.NET 0.8也一并登上舞台。新的推荐场景ML.NET使用基于矩阵分解(Matrix Factorization)和场感知分解机(Field-aware Factorization Mac…

F-Lucky Pascal Triangle(Lucas+数位dp)

F-Lucky Pascal Triangle issue是fw题解 下面代码TLE了&#xff0c;但是此题数位dp的思想非常值得学习 Lucas的过程相当于把n,mn,mn,m在p进制下的每一位拿出来做组合数 Lucas(n,m,p)∏(nkmk)modp\text{Lucas}(n,m,p)\prod \dbinom {n_k}{m_k} \bmod pLucas(n,m,p)∏(mk​nk​…

树的合并(ybtoj-树上dp)

文章目录题目描述前言解析代码thanks for reading&#xff01;题目描述 前言 全网唯一AC&#xff01;&#xff01;&#xff01; 妙啊 而且还是完全自己想出来的做法 开心 &#xff08;APIO还是没白听&#xff09; 但是思路出来后代码实现十分坎坷 建两个图分别dfs3次那个地方…

牛客题霸 [矩阵元素查找] C++题解/答案

牛客题霸 [矩阵元素查找] C题解/答案 题目描述 已知int一个有序矩阵mat&#xff0c;同时给定矩阵的大小n和m以及需要查找的元素x&#xff0c;且矩阵的行和列都是从小到大有序的。设计查找算法返回所查找元素的二元数组&#xff0c;代表该元素的行号和列号(均从零开始)。保证元…

51nod1821-最优集合【贪心】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1821 题目大意 nnn个可重集合&#xff0c;TTT次询问&#xff0c;询问将集合SxS_xSx​和一个选出大小为kkk的SyS_ySy​的子集合并成的独立集S′SS′满足能够找到一个最大的zzz使得对于任意的正整数i∈[1,z…

.net core中的高效动态内存管理方案

.net core在新增的System.Buffers中引入了一大堆高效内存管理的类&#xff0c;如span和memory、内存池。本文今天这里介绍一个高效动态内存访问方案。ReadOnlySequenceSegment<T>在我们读取数据的过程&#xff0c;很多时候会出现如下场景&#xff1a;不知道数据实际大小一…

C. Sum of Log(数位dp)

C. Sum of Log Code1 暴力记的状态 TLE #include<bits/stdc.h> using namespace std; using lllong long; template <class Tint> T rd() {T res0;T fg1;char chgetchar();while(!isdigit(ch)) {if(ch-) fg-1;chgetchar();}while( isdigit(ch)) res(res<<…

APIO游记(5.19-5.23)

概要 本来以为钱基本是白花了 但惊喜的发现其实没有 APIO之后做了几道题&#xff0c;感觉对题目的分析能力增强了 大概虽然不会任何前置算法&#xff0c;但其中的思路多多少少还是吸收到一些 还有一枚Cu诶 针不戳 课程 5.19决策单调性与四边形不等式 第一天 见识到了天高地…

.net core 上 K8S(三)Yaml文件运行.netcore程序

正文上一章我们通过kubectl run简单运行了一个.netcore网站&#xff0c;但实际的开发中&#xff0c;我们都是通过yaml来实现的。1.编写yaml文件关于yaml文件的格式在此就不多描述了&#xff0c;不熟悉的可以去网上搜一下示例。2.运行yamlkubectl create -f netcore.yaml 我们可…