codeforces 961E. Tufurama(主席树)

传送门
一眼主席树 s b sb sb题(%%%树状数组大佬们)。
简化题意:求满足 x < y , y ≤ a x , x ≤ a y x<y,y\le a_x,x\le a_y x<y,yax,xay ( x , y ) (x,y) (x,y)数量。
那么直接用主席树模拟题意就行了。(写完发现权值线段树就行了但是懒得改了)
代码:

#include
#define ri register int
using namespace std;
typedef long long ll;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=2e5+5;
int n,rt[N],ls[N*30],rs[N*30],siz[N*30],tot=0,a[N];
ll ans=0;
inline void update(int&p,int las,int l,int r,int k){
	p=++tot,ls[p]=ls[las],rs[p]=rs[las],siz[p]=siz[las]+1;
	if(l==r)return;
	int mid=l+r>>1;
	if(k<=mid)update(ls[p],ls[las],l,mid,k);
	else update(rs[p],rs[las],mid+1,r,k);
}
inline int query(int p,int ql,int qr,int l,int r){
	if(ql<=l&&r<=qr)return siz[p];
	int mid=l+r>>1;
	if(qr<=mid)return query(ls[p],ql,qr,l,mid);
	if(ql>mid)return query(rs[p],ql,qr,mid+1,qr);
	return query(ls[p],ql,mid,l,mid)+query(rs[p],mid+1,qr,mid+1,r);
}
int main(){
	freopen("lx.in","r",stdin);
	n=read();
	for(ri i=1;i<=n;++i)a[i]=min(read(),n),ans+=(ll)query(rt[min(a[i],i-1)],i,n,1,n),update(rt[i],rt[i-1],1,n,a[i]);
	cout<<ans;
	return 0;
}

你可能感兴趣的:(#,主席树,数据结构与分治算法,数据结构)