hdu-2688 Rotate---树状数组+模拟
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2688
题目大意:
给你n数,(n<=3e6),有两个操作,Q为 当前有多少对数,满足严格递增,R l,r为旋转l,r这个区间的数
解题思路:
求严格递增的顺序对我们可以反向用树状数组求逆序对,300W的数据还是有点够呛,不过这里求出来也就nlogn,然后对于旋转操作,因为区间大小不超过1000,我们只需统计该区间的第一个数和后面的数的关系,如果第一个数比后面的数大,就ans++,如果小于就ans--,等于就不管,因为是严格递增,然后就是这里我加入读入优化,感觉还是没什么卵用,反而比不加快,可能我写的优化不行吧。这题卡常数卡的有点紧,要注意常数优化,还有就是HDOJ的稳定性不是很好,同一个代码有时能过,有时不能过
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 #define N 10001 7 #define ll long long 8 #define Lowbit(x) ((x)&(-x)) 9 10 ll C[N]; 11 ll num[N*300]; 12 int T; 13 14 15 void add(ll C[],ll pos,ll num) { 16 while(pos <= N) {//x最大是N 17 C[pos] += num; 18 pos += Lowbit(pos); 19 } 20 } 21 22 ll Sum(ll C[],ll end) { 23 ll sum = 0; 24 while(end > 0) { 25 sum += C[end]; 26 end -= Lowbit(end); 27 } 28 return sum; 29 } 30 31 int main() { 32 int n, s, t, i, j, T, k; 33 ll ans, tmp; 34 while(~scanf("%d",&T)) { 35 memset(C,0,sizeof(C)); 36 ans = 0; 37 for(i = 0; i < T; i ++) { 38 scanf("%I64d",&num[i]); 39 add(C,num[i],1); 40 ans += Sum(C,num[i] - 1); 41 } 42 scanf("%d",&n); 43 char c[10]; 44 while(n--) { 45 scanf("%s",c); 46 switch(c[0]) { 47 case 'Q': 48 printf("%I64d\n",ans); 49 break; 50 case 'R': 51 scanf("%d%d",&s,&t); 52 int v = num[s]; 53 for(i = s; i < t; i++){ 54 num[i] = num[i + 1]; 55 if(v > num[i])ans++; 56 else if(v < num[i])ans--; 57 } 58 num[t] = v; 59 break; 60 } 61 } 62 63 } 64 return 0; 65 }
越努力,越幸运