1. 程式人生 > >2018.12.05 codeforces 961E. Tufurama(主席樹)

2018.12.05 codeforces 961E. Tufurama(主席樹)

傳送門
一眼主席樹 s b sb 題(%%%樹狀陣列大佬們)。
簡化題意:求滿足 x < y ,

y a x , x a y
x<y,y\le a_x,x\le a_y ( x , y ) (x,y)
數量。
那麼直接用主席樹模擬題意就行了。(寫完發現權值線段樹就行了但是懶得改了)
程式碼:

#include<bits/stdc++.h>
#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;
}