题意:
给长度为的数列,每次可以删除两个相同的数,加入,此时。
问你能得到的最大的数是多少。
为了增加难度,给了你次询问,每次修改一个数(对之后的询问都奏效),再问你同样的问题。
思路:
首先答案跟数列的排列顺序无关,跟不同值的个数有关。
也容易想到有两个相同的数就马上把它们合并(这是它们唯一的作用,总不能留着过年)
设表示值在中出现次数。
个值可以变成个,个可以变成……(总之这样下去)
得到实际的个数为无限嵌套,这个下取整好烦啊,把柿子化简为递推式得到:
这个柿子会清爽很多,含义是:对贡献的量,值的个数为。
所以最后求的是最大的 满足
首先中的最大值肯定是存在的,所以只用考虑大于出现的最大值,而且这部分的,即问题转化为的最大。
考虑维护,每次修改相当于一个另一个。
对的贡献,取决于下取整分子的奇偶性。
因此维护表示为奇(1)/偶(0)。
显然只会在为奇数的时候使,又往贡献。发现是找到从开始到满足都为的极大段**(),然后把区间+1,区间反转,别忘了也需要反转(我为这个调了好久)。
的增量以及奇偶性判断恰好是反过来的。
因此,我们需要:区间/单点修改(加),区间(单点)查询,找从开始为的极长段,找最靠右的的
最后一个操作直接二分,倒数第二个操作先要找到划分(找到的顺序自然是从左往右的),然后对于一个划分如果全部满足就结束讨论下一个,否则再分治(二分)下去。因为只有一个划分(区间)会分治下去,再加上所有的操作总复杂度为
然而我看到其它人很短的代码,就知道我的思路太逊了,不过能自己解出来题也很开心啦。
code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,q,a[N],c[N],F[N],ls[N],nd,rs[N];
priority_queue<int> Q;
int D[N]; //可删堆
void Q_del() {
while(!Q.empty()&&D[Q.top()]) {D[Q.top()]--;Q.pop();}
}
struct seg {
int l,r,len,tg,tf,g,f;
}T[N];
void P_dw(int x) {
if(T[x].tg!=-1) {
T[ls[x]].tg=T[rs[x]].tg=T[x].tg;
if(!T[x].tg) {T[ls[x]].g=T[rs[x]].g=0;}
else {T[ls[x]].g=T[ls[x]].len;T[rs[x]].g=T[rs[x]].len;}
T[x].tg=-1;
}
if(T[x].tf) {
T[ls[x]].tf+=T[x].tf;T[rs[x]].tf+=T[x].tf;
T[ls[x]].f+=T[x].tf*T[ls[x]].len;T[rs[x]].f+=T[x].tf*T[rs[x]].len;
T[x].tf=0;
}
}
void P_up(int x) {
T[x].g=T[ls[x]].g+T[rs[x]].g;
T[x].f=T[ls[x]].f+T[rs[x]].f;
}
int Query(int x,int p) {
if(T[x].l==T[x].r) {return T[x].g;}
P_dw(x);
int mid=(T[x].l+T[x].r)>>1;
return (p<=mid)?Query(ls[x],p):Query(rs[x],p);
}
void Build(int &x,int l,int r) {
x=++nd; T[x]=(seg){l,r,r-l+1,-1,0,0,0};
if(l==r) {T[x].f=F[l];T[x].g=((F[l-1]+c[l])&1);return;}
int mid=(l+r)>>1;
Build(ls[x],l,mid),Build(rs[x],mid+1,r);
P_up(x);
}
void Update(int x,int l,int r,int dg,int df) {
if(l<=T[x].l&&T[x].r<=r) {
T[x].f+=df*T[x].len;T[x].g=(!dg)?0:T[x].len;
T[x].tf+=df;T[x].tg=dg;
return;
}
P_dw(x);
int mid=(T[x].l+T[x].r)>>1;
if(l<=mid) Update(ls[x],l,r,dg,df);
if(r>mid) Update(rs[x],l,r,dg,df);
P_up(x);
}
void update(int x,int p) { //g[p]^1
if(T[x].l==T[x].r) {T[x].g^=1;return;}
P_dw(x);
int mid=(T[x].l+T[x].r)>>1;
(p<=mid)?update(ls[x],p):update(rs[x],p);
P_up(x);
}
//g整段的值是否为vf
bool check(int x,int vg) {return T[x].g==(!vg?0:T[x].len);}
int findG(int x,int L,int vg) { //the rightest G (左边能满足,右边才可以)
if(T[x].r<L)return -1;
if(T[x].l==T[x].r) {
if(!check(x,vg))return -1;
return T[x].l;
}
if(T[x].l>=L) { //一段划分
if(check(x,vg)) return T[x].r;
P_dw(x);
if(check(ls[x],vg)) {return max(T[ls[x]].r,findG(rs[x],L,vg));}
else return findG(ls[x],L,vg);
}
P_dw(x);
int mid=T[ls[x]].r;
if(mid<L) return findG(rs[x],L,vg);
int w=findG(ls[x],L,vg); //先找到 [L,n]的划分(从左到右)
return w==mid?max(w,findG(rs[x],L,vg)):w;
}
int findF(int x,int L) { //the rightest F(只要最右边有一个满足了即可)
if(T[x].r<L) {return -1;}
if(T[x].l==T[x].r) {
assert(T[x].f>=0);
if(!T[x].f) return -1;
return T[x].l;
}
P_dw(x);
assert(T[rs[x]].f>=0);
if(!T[rs[x]].f) return findF(ls[x],L);
return findF(rs[x],L);
}
void Del(int x) {
int w=Query(1,x);
// printf("Del x=%d c[x]=%d w=%d\n",x,c[x],w);
if(!(w&1)) {
int r=findG(1,x,0);
assert(r!=-1); //*
// printf("!r=%d\n",r);
Update(1,x,r,1,-1);
if(r<m)update(1,r+1);
}
else {update(1,x);}
c[x]--;
}
void Add(int x) {
int w=Query(1,x);
// printf("Add x=%d c[x]=%d w=%d\n",x,c[x],w);
if(w&1) {
int r=findG(1,x,1);
assert(r!=-1);
// printf("!r=%d\n",r);
Update(1,x,r,0,1);
if(r<m)update(1,r+1);
}
else {update(1,x);}
c[x]++;
}
int main() {
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){scanf("%d",&a[i]);c[a[i]]++;Q.push(a[i]);}
m=2e5+20; //+log次
for(int i=1;i<=m;i++) {F[i]=(F[i-1]+c[i])/2;}
int rt;Build(rt,1,m);
while(q--) {
int k,v;
scanf("%d%d",&k,&v);
D[a[k]]++;Q.push(v);Q_del();
Del(a[k]),Add(v);
a[k]=v;
int mx=Q.top();
// printf("mx=%d\n",mx);
int r=findF(1,mx);
// printf("r=%d\n",r);
printf("%d\n",(r==-1)?mx:r+1);
}
return 0;
}
//完结撒花
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
2021-07-16 整除分块
2021-07-16 冰茶鸡