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 }

 

posted @ 2018-04-27 21:23  _努力努力再努力x  阅读(142)  评论(0编辑  收藏  举报