AcWing 241.楼兰图腾 (树状数组,逆序对)
-
题意:在二维坐标轴上给你一些点,求出所有由三个点构成的v和∧图案的个数.
-
题解:因为给出的点是按横坐标的顺序给出的,所以我们可以先遍历然后求出某个点左边比它高和低的点的个数(这个过程简直和用树状数组求逆序对的操作一模一样好不好!),用\(grt[i]\)记录第\(i\)个点左边比它大的数,\(low[i]\)表示比它小的数,然后我们再对树状数组清空,反着求一下每个点右边的情况,这次不用再记录了,直接求贡献给答案即可.
-
代码:
#define int long long int n; int a[N]; int c[N]; int grt[N],low[N]; int res1,res2; int lowbit(int x){ return x&(-x); } void updata(int i,int k){ while(i<=n){ c[i]+=k; i+=lowbit(i); } } int get_sum(int i){ int res=0; while(i){ res+=c[i]; i-=lowbit(i); } return res; } signed main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n; rep(i,1,n) cin>>a[i]; rep(i,1,n){ //每个点左边的greater和lower int cur=a[i]; grt[i]=get_sum(n)-get_sum(cur); low[i]=get_sum(cur-1); updata(cur,1); } me(c,0,sizeof(c)); per(i,n,1){ //求每个点右边的greater和lower,以及更新答案 int cur=a[i]; res1+=grt[i]*(get_sum(n)-get_sum(cur)); res2+=low[i]*get_sum(cur-1); updata(cur,1); } cout<<res1<<' '<<res2; return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮