Sherlock and Inversions CodeChef - IITI15(莫队+树状数组)

    xiaoxiao2024-12-19  62

    题目:点击此处

    给你n个数,q个询问,每次询问一个区间内的逆序对的对数

    莫队套上树状数组即可

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <map> #define ll long long using namespace std; const int maxn=1e6+5; map<int,int> mp; int n,t=0,k; struct node { int a,i; }pos[maxn]; struct node1 { int l,r,i; }pos1[maxn]; int block; bool cmp(node1 a,node1 b) { if(a.l/block!=b.l/block)return a.l/block<b.l/block; return a.r<b.r; } bool cmp1(node a,node b) { return a.a<b.a; } bool cmp2(node a,node b) { return a.i<b.i; } int c[maxn],a,answer[maxn],q,ans,INDEX; int lowbit(int x) { return x&(-x); } void add(int x,int y){ for(int i=x;i<=INDEX;i+=lowbit(i)) c[i] += y; } int getsum(int x){ int ans1 = 0; for(int i=x;i;i-=lowbit(i)) ans1 += c[i]; return ans1; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a); pos[i].a=a; pos[i].i=i; } sort(pos+1,pos+n+1,cmp1); INDEX=0; for(int i=1;i<=n;i++) { if(mp[pos[i].a]==0) { INDEX++; mp[pos[i].a]=INDEX; } } block=sqrt(1.0*n); sort(pos+1,pos+n+1,cmp2); scanf("%d",&q); for(int i=1;i<=q;i++) { scanf("%d%d",&pos1[i].l,&pos1[i].r); pos1[i].i=i; } sort(pos1+1,pos1+q+1,cmp); int cl=1,cr=0; for(int i=1;i<=q;i++) { int l=pos1[i].l,r=pos1[i].r,j; if(l==r) { answer[pos1[i].i]=0; continue; } while(cr<r) { int re=getsum(mp[pos[cr+1].a]); ans+=(cr+1-cl-re); add(mp[pos[cr+1].a],1); cr++; } while(cr>r) { int re=getsum(mp[pos[cr].a])-1; ans-=(cr-cl-re); add(mp[pos[cr].a],-1); cr--; } while(cl<l) { add(mp[pos[cl].a],-1); int re=getsum(mp[pos[cl].a] - 1); ans-=re; cl++; } while(cl>l) { ans+=getsum(mp[pos[cl-1].a] - 1); add(mp[pos[cl-1].a], 1); cl--; } answer[pos1[i].i]=ans; } for(int i=1;i<=q;i++) printf("%d\n",answer[i]); return 0; }

     

    最新回复(0)