传送门
一眼主席树
s
b
sb
sb题(%%%树状数组大佬们)。
简化题意:求满足
x
<
y
,
y
≤
a
x
,
x
≤
a
y
x<y,y\le a_x,x\le a_y
x<y,y≤ax,x≤ay的
(
x
,
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;
}

本文介绍了一种使用主席树解决特定数对问题的方法,旨在计算满足特定条件的(x,y)数量,通过构建和更新主席树来实现高效查询。
&spm=1001.2101.3001.5002&articleId=84827039&d=1&t=3&u=237458c22505459c86afe593c28fa78b)
301

被折叠的 条评论
为什么被折叠?



