题目链接:点击打开链接
题意描述:对一个长度为2<=n<=3000000的数组,求数组中有序对(i<j并且F[i]<F[j])的数量?其中数组元素F[i]范围(0<F[i]<=10000),现有m<10000个操作
操作一:R x y(其中y-x<=1000)将数组x~y之间的元素旋转
操作二:Q查询当前数组中含有的有序对的数量
解题思路:
1、先求的原始数组中有序对的总数量(如果直接求,则时间复杂度为O(n*10000);如果使用树状数组时间复杂度为O(nlgn))即O(n*14)
2、对于每次操作一,循环遍历F[x+1]~F[y]中元素与F[x]的关系,对总数量进行加减即可O(1000*m)
3、对于操作二,直接输出总数量即可(O(1))
代码:
#include <cstdio> #include <cstring> #define MAXN 3000010 using namespace std; int d[MAXN]; int C[10010]; int n,m; int lowbit(int x) { return x&(-x); } int sum(int pos) { int res=0; while(pos>0) { res+=C[pos]; pos-=lowbit(pos); } return res; } void add(int pos,int v) { while(pos<=10000) { C[pos]+=v; pos+=lowbit(pos); } } int main() { while(scanf("%d",&n)!=EOF) { memset(C,0,sizeof(C)); long long ans=0; for(int i=0; i<n; i++) { scanf("%d",&d[i]); add(d[i],1); ans+=sum(d[i]-1); } scanf("%d",&m); char st[10]; for(int i=1; i<=m; ++i) { scanf("%s",st); switch(st[0]) { case 'Q': printf("%I64d\n",ans); break; case 'R': int l,r; scanf("%d%d",&l,&r); int v=d[l]; for(int j=l+1; j<=r; j++) { if(d[j]>v) ans--; else if(d[j]<v) ans++; d[j-1]=d[j]; } d[r]=v; break; } } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-17 15:12:20