首页 > 其他分享 >[JXOI2017] 加法 题解

[JXOI2017] 加法 题解

时间:2024-11-14 22:00:15浏览次数:1  
标签:lazy JXOI2017 int 题解 mid st 端点 加法 区间

[JXOI2017] 加法

最小值最大,一眼二分。贪心地,每次尽量对包含当前序列最小值的区间做加法操作,也就是说,对于当前二分的答案 \(x\),任何的 \(A_i<x\) 都需要被操作。

从左到右地考虑答案。我们认为当前点之前的所有值都已经满足条件,于是我们只需考虑每次区间对当前点之后答案造成的贡献。于是我们将所有区间按左端点为第一关键字排序,而在左端点相同的所有区间当中,我们选择右端点最靠右的区间,以覆盖更多的元素

每一次从 \(i-1\) 到 \(i\) 的过程中,加入左端点在 \(i\) 的区间并删除右端点在 \(i-1\) 的区间,就可以动态维护覆盖当前点的区间。用一个以右端点为第一关键字排序的优先队列维护右端点最靠右的区间,每次对于这个区间加 \(a\),直到当前点的值 \(\ge x\)。任何时候若没有能覆盖 “需要被操作” 的点的区间,或所有区间加完了之后这个点仍 \(<x\),则不可行;反之当前答案可行。

需要一个支持区间修改、单点查询的数据结构,线段树和树状数组皆可。

#include<bits/stdc++.h>
#define fw fwrite(obuf,p3-obuf,1,stdout)
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<1<<20?(*p3++=(x)):(fw,p3=obuf,*p3++=(x)))
using namespace std;

char buf[1<<20],obuf[1<<20],*p1=buf,*p2=buf,*p3=obuf,str[20<<2];
int read(){
	int x=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x;
}
template<typename T>
void write(T x,char sf='\n'){
	if(x<0)putchar('-'),x=~x+1;
	int top=0;
	do str[top++]=x%10,x/=10;while(x);
	while(top)putchar(str[--top]+48);
	if(sf^'#')putchar(sf);
}
using ll=long long;
constexpr int MAXN=2e5+5;
int T,n,m,k,A;
ll a[MAXN];
struct{
	ll st[MAXN<<2],lazy[MAXN<<2];
	#define lp p<<1
	#define rp p<<1|1
	#define mid ((s+t)>>1)
	void build(int s,int t,int p){
		st[p]=lazy[p]=0;
		if(s==t)return st[p]=a[s],void();
		build(s,mid,lp),build(mid+1,t,rp);
		st[p]=st[lp]+st[rp];
	}
	void pushdown(int s,int t,int p){
		if(!lazy[p]) return;
		st[lp]+=(mid-s+1)*lazy[p],st[rp]+=(t-mid)*lazy[p];
		lazy[lp]+=lazy[p],lazy[rp]+=lazy[p];
		lazy[p]=0;
	}
	void mdf(int l,int r,ll k,int s=1,int t=n,int p=1){
		if(l<=s&&t<=r) return st[p]+=(t-s+1)*k,lazy[p]+=k,void();
		pushdown(s,t,p);
		if(l<=mid) mdf(l,r,k,s,mid,lp);
		if(mid<r) mdf(l,r,k,mid+1,t,rp);
		st[p]=st[lp]+st[rp];
	}
	ll sum(int x,int s=1,int t=n,int p=1){
		if(s==t) return st[p];
		pushdown(s,t,p);
		if(x<=mid) return sum(x,s,mid,lp);
		return sum(x,mid+1,t,rp);
	}
	#undef mid
}ST;
struct SH{
	int l,r;
	bool operator<(const SH&x)const{
		return r<x.r;
	}
}p[MAXN],t;

bool check(ll x){
	priority_queue<SH>q;
	ST.build(1,n,1);
	int lst=1,cnt=0;
	for(int i=1;i<=n;++i){
		while(lst<=m&&p[lst].l<=i) q.emplace(p[lst++]);
		while(!q.empty()&&ST.sum(i)<x){
			do t=q.top(),q.pop();
			while(!q.empty()&&t.r<i);
			if(t.r<i||++cnt>k) return 0;
			ST.mdf(t.l,t.r,A);
		}
		if(ST.sum(i)<x) return 0;
	}
	return 1;
}

int main(){
	T=read();
	while(T--){
		n=read(),m=read(),k=read(),A=read();
		ll l=2e18,r=0;
		for(int i=1;i<=n;++i) a[i]=read(),l=min(l,a[i]),r=max(r,a[i]);
		r+=k*A;
		for(int i=1;i<=m;++i) p[i]={read(),read()};
		sort(p+1,p+m+1,[&](const SH&x,const SH&y){
			return x.l<y.l;
		});
		ll mid,ans=l;
		while(l<=r){
			mid=(l+r)>>1;
			if(check(mid)) l=mid+1,ans=mid;
			else r=mid-1;
		}
		write(ans);
	}
	return fw,0;
}

标签:lazy,JXOI2017,int,题解,mid,st,端点,加法,区间
From: https://www.cnblogs.com/laoshan-plus/p/18546916

相关文章

  • 题解:P7836 「Wdoi-3」夜雀 collecting
    题解摘自做题记录。分析数据范围明显得要让我们分开搞。【Sub2】应该是暴力。这里有个主体思路,我们完全可以贪心地将当前背包里的食材删掉,直到每种出现过的食材数量刚好为\(1\)。因为我们保留更多的是没有用的。那么我们就可以用二进制数表示\(x\)种食材的出现状态了。同......
  • 【题解】CF1982
    A考虑两队的领先情况改变,那么一定有某一时刻两队的比分相等于是首先检查最开始的领先队伍,再检查现在的领先队伍,如果前后不同,则\(YES\),否则\(NO\)B注意到当\(x=1\),则会进入循环,手模一下发现\(ans=k\%(y-1)+1)\)现在的问题是:什么时候\(x=1\)?直接手动模拟即可,不难证明时......
  • Intellij IDEA如何设置中文版?安装中文汉化包插件?失败问题解决!
    前言大家好,我是小徐啊。IntellijIDEA默认是英文的操作界面,因为是外国人开发的嘛~对于英文好一点的同学来说,英文就英文吧,但对于英文比较差的同学,就还是希望能够汉化一下,变成熟悉的中文。今天小徐就来介绍下如何在IDEA中安装汉化插件,以及在这过程中,我遇到的奇怪问题,以及最后如何......
  • P8099 [USACO22JAN] Minimizing Haybales P 题解
    好题图论的难点在于建图~首先我们关注到如果两个草堆之间的差大于K,那么他们的位置就是固定的,就相当于给了一些限制,这就是很经典的连边然后拓扑排序。其实你是不是可以直接从小的向大的连边(我没试)然后再做排序。这一部分代码(粗略验证正确性,赶着写的,可能比较一言难尽)#include<bi......
  • 【考试题解】NOIP2024(欢乐)加赛3
    目录A.SakurakoandWater题目内容思路代码B.BinomialCoefficients,KindOf题目内容思路代码C.QED'sFavoritePermutation题目内容思路代码D.CardGame题目内容思路代码E.LongWaytobeNon-decreasing题目内容思路代码F.ManyGames题目内容思路代码A.SakurakoandW......
  • COCI19-20#6 Trener题解
    COCI19-20#6Trenerlink一道水题(我真是太弱了啊啊啊啊。众所周知,看到这个题立刻知道他是要选名字长度为$1$到$N$的,而我们知道他每一个名字,所以可以直接用字符哈希去做,因为他每一个名字的字符数是上一层名字的字符数加一,所以对于哈希每个字符串只需要跑三次,分别是自己的这......
  • 【题解】洛谷P11186: 三目运算
    不好玩!!!这是个树形结构,直接暴力模拟,但过不去,但是需要发现答案是个区间,我们对字符串处理时记录最大值最小值,然后到叶子节点时我们将此时的区间存起来,查询时直接二分查询这个数对于的区间就可以了。总结:不好玩!!!#include<bits/stdc++.h>usingnamespacestd;#definelllonglon......
  • 【题解】洛谷P1712: [NOI2016] 区间
    P1712[NOI2016]区间我对尺取法并不敏感,所以感觉有点难度,我们想到按照区间长度排序加入使得满足单调性,直到有一个区间的覆盖次数达到了m就可以计算了,而这个就是尺取法,单调性使得我们答案总是最优的。覆盖次数就可以用线段树做,而且数据范围很大需要离散化,计算答案时注意把答案带......
  • 题解:P11251 [GESP202409 八级] 美丽路径
    题目传送门题目大意给你一颗树,每个结点为黑色或白色。求一条路径,使得路径上距离为奇数的点颜色不同,距离为偶数的点颜色相同,输出这条路径最多能包含多少结点。思路讲解容易想到用树形动态规划搭配dfs解决。将结点1......
  • 2021年6月上海月赛T5题解(做基础123题时遇到的)
    平衡点内存限制: 256 Mb时间限制: 1000 ms题目描述给定一个由 n 个整数组成的数列a1​,a2​,⋯,an​,请为这个数列找到一个平衡点,使得平衡点左侧与右侧的力矩尽量接近。若平衡点为 ak​,则左侧力矩定义为数列中下标小于 k 的各个元素到 ak​ 的距离乘以这些元素......