CF961E Tufurama

链接:

CF961E


题意:

给出长度为 \(n(1\leq n\leq 2\times10^5)\) 的序列 \(a(1\leq a_i\leq10^9)\),求满足 \(1\leq i< j\leq n\)\(a_i\geq j,a_j\geq i\) 的二元组 \((i,j)\) 的数量。


分析:

对于一个位置 \(j\),考虑它前面所有能与它满足条件的 \(i\) 的数量,于是有 \(i< j\)\(a_j\geq i\) 所以只考虑 \([1,\min(j-1,a_j)]\) 位置的数,同时需要满足 \(a_i\geq j\)。所以我们要做的是从前往后扫一遍,对于每个位置 \(j\),求出 \([1,\min(j-1,a_j)]\)\(a_i\geq j\)\(i\) 的数量。可以对每个位置建一棵权值线段树记录 \([1,j]\) 中的所有 \(a_i\),使用主席树就可以 \(O(n\log n)\) 过掉此题。注意要对 \(a\) 序列离散化,且由于要比较 \(a_i\)\(j\) 所以在离散化时要注意同时离散化 \([1,n]\)


代码:
#include<bits/stdc++.h>
using namespace std;
#define in read()
inline int read(){
	int p=0,f=1;
	char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
	return p*f;
}
const int N=4e5+5;
int n,a[N],q[N],qn;
long long ans;
inline int bin(int key){
	int l=1,r=qn,mid;
	while(l<r){
		mid=(l+r)>>1;
		if(q[mid]<key)l=mid+1;
		else r=mid;
	}
	return l;
}
//sgt--------------------
int rt[N],sum[N<<5],lc[N<<5],rc[N<<5],tot;
void pushup(int p){sum[p]=sum[lc[p]]+sum[rc[p]];}
int newnode(){
	sum[++tot]=lc[tot]=rc[tot]=0;
	return tot;
}
int built(int l,int r){
	int p=newnode();
	if(l==r)return p;
	int mid=(l+r)>>1;
	lc[p]=built(l,mid);
	rc[p]=built(mid+1,r);
	return p;
}
int newbuilt(int pre,int l,int r,int x,int d){
	int now=newnode();
	sum[now]=sum[pre];
	lc[now]=lc[pre];
	rc[now]=rc[pre];
	if(l==r){sum[now]+=d;return now;}
	int mid=(l+r)>>1;
	if(x<=mid)lc[now]=newbuilt(lc[now],l,mid,x,d);
	else rc[now]=newbuilt(rc[now],mid+1,r,x,d);
	pushup(now);
	return now;
}
int query(int l,int r,int p,int ql,int qr){
	if(l>=ql&&r<=qr)return sum[p];
	int mid=(l+r)>>1,res=0;
	if(ql<=mid)res+=query(l,mid,lc[p],ql,qr);
	if(qr>mid)res+=query(mid+1,r,rc[p],ql,qr);
	return res;
}
//-----------------------------------
signed main(){
	n=in;
	for(int i=1;i<=n;i++)a[i]=in,q[i]=a[i];
	for(int i=1;i<=n;i++)q[i+n]=i;
	sort(q+1,q+1+2*n);
	qn=unique(q+1,q+1+2*n)-(q+1);
	for(int i=1;i<=n;i++)a[i]=bin(a[i]);
	rt[0]=built(1,qn);
	for(int i=1;i<=n;i++){
		int t=min(i-1,a[i]);
		ans+=query(1,qn,rt[t],i,qn);
		rt[i]=newbuilt(rt[i-1],1,qn,a[i],1);
	}
	cout<<ans;
	return 0;
}

posted @ 2021-08-29 16:10  llmmkk  阅读(47)  评论(0编辑  收藏  举报