hdu_2688_Rotate(树状数组)

题目连接:hdu_2688_Rotate

题意:给你n数,(n<=3e6),有两个操作,Q为 当前有多少对数,满足严格递增,R l,r为旋转l,r这个区间的数

题解:求严格递增的顺序对我们可以反向用树状数组求逆序对,300W的数据还是有点够呛,不过这里求出来也就nlogn,然后对于旋转操作,因为区间大小不超过1000,我们只需统计该区间的第一个数和后面的数的关系,如果第一个数比后面的数大,就ans++,如果小于就ans--,等于就不管,因为是严格递增,然后就是这里我加入读入优化,感觉还是没什么卵用,反而比不加快,可能我写的优化不行吧。这题卡常数卡的有点紧,要注意常数优化,还有就是HDOJ的稳定性不是很好,同一个代码有时能过,有时不能过

#include<cstdio>
#include<cstring>
#define F(i,a,b) for(int i=a;i<=b;++i)
typedef long long LL;
int sum[10010],a[3000010];char op[2];

inline void add(int x,int c){while(x<=10000)sum[x]+=c,x+=x&-x;}
inline int ask(int x){int ans=0;while(x>0)ans+=sum[x],x-=x&-x;return ans;}

int main(){
    int n,m;
    while(~scanf("%d",&n)){
        memset(sum,0,sizeof(sum));
        LL ans=0;
        F(i,0,n-1)scanf("%d",&a[i]),ans+=ask(a[i]-1),add(a[i],1);
        scanf("%d",&m);
        F(i,1,m){
            scanf("%s",op);
            if(op[0]=='Q')printf("%I64d\n",ans);
            else{
                int l,r;
                scanf("%d%d",&l,&r);
                int now=a[l];
                F(i,l+1,r){
                    if(a[i]>now)ans--;
                    else if(a[i]<now)ans++;
                    a[i-1]=a[i];
                }
                a[r]=now;
            }
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章