ST表求调
查看原帖
ST表求调
225375
Cuxhin楼主2024/6/23 16:59

能过样例,自己造数据也找不出问题,却只能过两个点(#1#4)。

与题解上往下数第三篇思路比较相似(自己写的不是抄的,写完才看到这么像)。

万分感谢调教,蒟蒻写倍增的信息都快被这题击碎了。

//Cuxhin、初心 
#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int N = 5*1e5+10;//n的最值 
int n,kk,L,R;//分别对应题目n,k,L,R 
ll ans=0;//答案 
ll s[N];//前缀和 
int f[N][25];//st表,存的是坐标(第几个音符) 
class Node{//优先队列的类,区间 
public:
	//注:我这里是半开区间(i,t],后面同理 
	int i,t,l,r;//以i为起点前一步,s[t]-s[i]最大时的t(前缀和最大),区间范围l,r 
	Node(){
		
	}
	Node(int a,int b,int c,int d):i(a),l(b),r(c),t(d){//构造函数 
	}
	friend bool operator<(Node a,Node b){//优先队列以值最大排序 
		return (s[a.t]-s[a.i])<(s[b.t]-s[b.i]);
	}
};
priority_queue<Node> q;
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	scanf("%d%d%d%d",&n,&kk,&L,&R);
	for(int i=1;i<=n;i++){
		scanf("%lld",&s[i]);
		s[i]+=s[i-1];//前缀和 
		f[i][0]=i;//初始化st表 
	}
	//st表的构造,以i为起点,长度2^k的区间,[i,i+2^k-1] 
	for(int k=1;(1<<k)<=n;k++){//2^k长度的区间 
		for(int i=1;i+(1<<k)-1<=n;i++){//第i为起点 
			if(s[f[i][k-1]]>=s[f[i+(1<<(k-1))][k-1]]){//2^k分割成2^(k-1)左边区间
				f[i][k]=f[i][k-1]; 
			}
			else{
				f[i][k]=f[i+(1<<(k-1))][k-1];
			}
		}
	}
	//初始化优先队列 
	for(int i=0,k=log2(R-L+1),tR;i+L<=n;i++){
		if(i+R>n){//这里是处理i+R过n的情况,临时修改区间的最大长度,不然会i+R会过n 
			tR=n-i;
			k=log2(tR-L+1);//k只会越改越小 
		}
		else tR=R;//为了方便后面也用tR存R了 
		//查询区间的最值
		if(s[f[i+L][k]]>=s[f[(i+tR)-(1<<k)+1][k]]){ 
			q.push(Node(i,L,tR,f[i+L][k]));
		}
		else{
			q.push(Node(i,L,tR,f[(i+tR)-(1<<k)+1][k]));			
		}
	}
	//输出kk(题目中的k,为了避免冲突双写了)个答案 
	while(kk--){
		Node tmp=q.top();//找队头,区间和最大的 
		q.pop();//弹出 
		int i=tmp.i,l=tmp.l,r=tmp.r,t=tmp.t;//拆开并临时存储队头 
		ans+=(s[t]-s[i]);//加入答案 
		if(t-i!=l){//左边能拆 
			int nr=(t-1)-i,k=log2((nr-l+1));//新的最大区间长度
			//查找新区间最值 
			if(s[f[i+l][k]]>=s[f[(i+nr)-(1<<k)+1][k]]){
				q.push(Node(i,l,nr,f[i+l][k]));
			}
			else{
				q.push(Node(i,l,nr,f[(i+nr)-(1<<k)+1][k]));			
			}
		}
		if(t-i!=r){//右边能拆 
			int nl=(t+1)-i,k=log2(r-nl+1);//新的最短区间长度
			//查找新区间最值 
			if(s[f[i+nl][k]>=s[f[(i+r)-(1<<k)+1][k]]]){
				q.push(Node(i,nl,r,f[i+nl][k]));
			}
			else{
				q.push(Node(i,nl,r,f[(i+r)-(1<<k)+1][k]));
			}
		}
			
	}
	printf("%lld",ans);
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}
2024/6/23 16:59
加载中...