gym265564 C

向右扩展右端点\(i\)

对于每一个\(k<i\):

  1. 维护\(\min\{pre_{k+1}...pre_i\}=r\)

  2. 维护最小的\(l\)满足\(\max\{nex_{l+1}...nex_{k}\}\leq i\Leftrightarrow \forall_{l< j\leq k} [ok_j]\Leftrightarrow \text{the last j} \leq k \text{ that ok[j]=0},ok[j]\ is\ [nex[j]\leq i]\)

\(k\)的答案为\(\max(r-l,0)\)

线段树实现区间\(+/-\),求全局正数和。

每次扩展右端点,\(r\)变小,\(l\)变小。

\(r_i,l_i\)都是递增的。

每次区间减小\(r_i\),需要找到一段后缀进行修改。

每次区间减小\(l_i\),需要找到一段前缀进行修改。

code:

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=2e5+233;
int n,a[MAXN],las[MAXN],pre[MAXN],nex[MAXN];
vector<int> tol[MAXN];
set<int> nok;
const int N=1<<18;
LL sum[N+N];
LL tag[N+N];
int cnt[N+N];
void pd(int now){
	sum[now]+=1ll*cnt[now]*tag[now];
	if(now<N) tag[now<<1]+=tag[now],tag[now<<1|1]+=tag[now];
	tag[now]=0;
}
LL queryrange(int a,int b,int now=1,int l=1,int r=N+1){
	pd(now);
	if(r<=a||l>=b) return 0;
	if(r<=b&&l>=a) return sum[now];
	int mid=(l+r)>>1;
	return queryrange(a,b,now<<1,l,mid)+queryrange(a,b,now<<1|1,mid,r);
}
void add(int a,int b,int val,int now=1,int l=1,int r=N+1){
	pd(now);
	if(r<=a||l>=b) return ;
	if(r<=b&&l>=a){
		tag[now]+=val;
		pd(now);
		return ;
	}
	int mid=(l+r)>>1;
	add(a,b,val,now<<1,l,mid);
	add(a,b,val,now<<1|1,mid,r);
	sum[now]=sum[now<<1]+sum[now<<1|1];
}
LL gt(int pos,int now=1,int l=1,int r=N+1){
	pd(now);
	if(l==r-1) return sum[now];
	int mid=(l+r)>>1;
	if(mid>pos)return gt(pos,now<<1,l,mid);
	return gt(pos,now<<1|1,mid,r);
}
LL Ans=0;
void modifyl(int l,int r,int val){//l+val
	//find the first position which is positive
	int lb,br;
	lb=l,br=r+1;
	while(lb<br){
		int mid=(lb+br)>>1;
		if(gt(mid)>=0) br=mid;
		else lb=mid+1;
	}
	Ans-=queryrange(lb,r+1);
	add(l,r+1,-val);
	lb=l,br=r+1;
	while(lb<br){
		int mid=(lb+br)>>1;
		if(gt(mid)>=0) br=mid;
		else lb=mid+1;
	}
	Ans+=queryrange(lb,r+1);
}
void modifyr(int l,int r,int val){//r+val
	//find the last position which is positive
	int lb,br;
	lb=l-1,br=r+1;
	while(lb<br-1){
		int mid=(lb+br)>>1;
		if(gt(mid)>=0) lb=mid;
		else br=mid;
	}
	Ans-=queryrange(l,lb+1);
	add(l,r+1,val);
	lb=l-1,br=r+1;
	while(lb<br-1){
		int mid=(lb+br)>>1;
		if(gt(mid)>=0) lb=mid;
		else br=mid;
	}
	Ans+=queryrange(l,lb+1);
}
int main(){
	rb(i,N,N+N-1) cnt[i]=1;
	rl(i,N-1,1) cnt[i]=cnt[i<<1]<<1; 
	scanf("%d",&n);
	rb(i,1,n) scanf("%d",&a[i]);
	rb(i,1,n) pre[i]=las[a[i]],las[a[i]]=i;
	fill(las+1,las+1+n,n+1);
	rl(i,n,1) nex[i]=las[a[i]],las[a[i]]=i;
	rb(i,1,n) tol[nex[i]].PB(i);
	nok.insert(0);
	nok.insert(n+1);
	rb(i,1,n) nok.insert(i);
	LL rest=0;
	stack<mp> r;
	rb(i,1,n) modifyl(i,i,i);
	rb(j,2,n){
		for(auto it:tol[j]){
			auto ite=nok.find(it);
			modifyl(*ite,*next(ite)-1,*prev(ite)-*ite);
			nok.erase(ite);
		}
		int L=j-1;
		while(!r.empty()&&r.top().SEC>=pre[j]){
			modifyr(r.top().FIR,L-1,pre[j]-r.top().SEC);
			L=r.top().FIR;
			r.pop();
		}
		modifyr(j-1,j-1,pre[j]);
		r.push(II(L,pre[j]));
		rest+=Ans;
	}
	cout<<rest<<endl;
	return 0;
}
posted @ 2021-06-22 09:24  WWW~~~  阅读(93)  评论(0编辑  收藏  举报