首页 > 代码库 > BZOJ 3744: Gty的妹子序列

BZOJ 3744: Gty的妹子序列

3744: Gty的妹子序列

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1335  Solved: 379
[Submit][Status][Discuss]

Description

我早已习惯你不在身边,
人间四月天 寂寞断了弦。
回望身后蓝天,
跟再见说再见……
某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现
她们排成了一个序列,每个妹子有一个美丽度。
Bakser神犇与他打算研究一下这个妹子序列,于是Bakser神犇问道:"你知道区间
[l,r]中妹子们美丽度的逆序对数吗?"
蒟蒻Autumn只会离线乱搞啊……但是Bakser神犇说道:"强制在线。"
请你帮助一下Autumn吧。
给定一个正整数序列a,对于每次询问,输出al...ar中的逆序对数,强制在线。

Input

第一行包括一个整数n(1<=n<=50000),表示数列a中的元素数。
第二行包括n个整数a1...an(ai>0,保证ai在int内)。
接下来一行包括一个整数m(1<=m<=50000),表示询问的个数。
接下来m行,每行包括2个整数l、r(1<=l<=r<=n),表示询问al...ar中的逆序
对数(若ai>aj且i<j,则为一个逆序对)。
l,r要分别异或上一次询问的答案(lastans),最开始时lastans=0。
保证涉及的所有数在int内。

Output

对每个询问,单独输出一行,表示al...ar中的逆序对数。

Sample Input

4
1 4 2 3
1
2 4

Sample Output

2

HINT

Source

By Autumn

[Submit][Status][Discuss]

 

╮(╯▽╰)╭  Gty的撩妹技能我等蒟蒻就是不能比。

 

分块+主席树+树状数组 随便搞一发就好了(其实调了好久)。

 

  1 #include <bits/stdc++.h>  2   3 namespace fastRead  4 {  5     inline int nextChar(void)  6     {  7         static const int siz = 1 << 20;  8   9         static char buf[siz]; 10         static char *hd = buf + siz; 11         static char *tl = buf + siz; 12  13         if (hd == tl) 14             fread(hd = buf, 1, siz, stdin); 15  16         return int(*hd++); 17     } 18  19     inline int nextInt(void) 20     { 21         register int ret = 0; 22         register int neg = false; 23         register int bit = nextChar(); 24  25         for (; bit < 48; bit = nextChar()) 26             if (bit == -)neg ^= true; 27  28         for (; bit > 47; bit = nextChar()) 29             ret = ret * 10 + bit - 0; 30  31         return neg ? -ret : ret; 32     } 33 } 34  35 const int mxn = 50005; 36  37 int n, m, h, s[mxn], lastAns = 0; 38  39 namespace chairManTree 40 { 41     const int siz = 1000005; 42  43     int tot; 44     int cnt[siz]; 45     int lsn[siz]; 46     int rsn[siz]; 47  48     int root[mxn]; 49  50     void insert(int &t, int p, int l, int r, int v) 51     { 52         t = ++tot; 53  54         lsn[t] = lsn[p]; 55         rsn[t] = rsn[p]; 56         cnt[t] = cnt[p] + 1; 57  58         if (l != r) 59         { 60             int mid = (l + r) >> 1; 61      62             if (v <= mid) 63                 insert(lsn[t], lsn[p], l, mid, v); 64             else 65                 insert(rsn[t], rsn[p], mid + 1, r, v); 66         } 67     } 68  69     int query(int a, int b, int l, int r, int x, int y) 70     { 71         if (l == x && r == y) 72             return cnt[a] - cnt[b]; 73          74         int mid = (l + r) >> 1; 75  76         if (y <= mid) 77             return query(lsn[a], lsn[b], l, mid, x, y); 78         else if (x > mid) 79             return query(rsn[a], rsn[b], mid + 1, r, x, y); 80         else 81             return query(lsn[a], lsn[b], l, mid, x, mid) + query(rsn[a], rsn[b], mid + 1, r, mid + 1, y); 82     } 83  84     inline void main(void) 85     { 86         for (int i = 1; i <= n; ++i) 87             insert(root[i], root[i - 1], 1, h, s[i]); 88     } 89  90     inline int query(int l, int r, int k) 91     { 92         if (k > 1) 93             return query(root[r], root[l - 1], 1, h, 1, k - 1); 94         else 95             return 0; 96     } 97 } 98  99 namespace binaryInsertTree100 {101     int tree[mxn];102 103     inline void add(int p, int v)104     {105         for (; p <= h; p += p&-p)106             tree[p] += v;107     }108 109     inline int qry(int p)110     {111         int ret = 0;112 113         for (; p >= 1; p -= p&-p)114             ret += tree[p];115 116         return ret;117     }118 119     inline void init(void)120     {121         memset(tree, 0, sizeof(tree));122     }123 }124 125 namespace divideSequence126 {127     const int mxt = 255;128 129     int t, st[mxt], tot, rev[mxt][mxn];130 131     inline int findStart(int k)132     {133         int lt = 1, rt = tot, mid, ans = 0;134 135         while (lt <= rt)136         {137             mid = (lt + rt) >> 1;138 139             if (st[mid] >= k)140                 rt = mid - 1, ans = mid;141             else142                 lt = mid + 1;143         }144 145         return ans;146     }147 148     inline void main(void)149     {150         t = int(sqrt(n) + 0.5);151 152         for (int i = 1, j = 1; i <= n; i += t, ++j)153         {154             st[j] = i;155 156             binaryInsertTree::init();157 158             for (int k = i, sum = 0; k <= n; ++k, ++sum)159             {160                 rev[j][k] = rev[j][k - 1];161                 rev[j][k] += sum - binaryInsertTree::qry(s[k]);162 163                 binaryInsertTree::add(s[k], 1);164             }165 166             tot = j;167         }168     }169 }170 171 namespace preworkHash172 {173     int map[mxn], tot;174 175     inline int find(int k)176     {177         int lt = 1, rt = tot, mid, ans;178 179         while (lt <= rt)180         {181             mid = (lt + rt) >> 1;182 183             if (map[mid] <= k)184                 lt = mid + 1, ans = mid;185             else186                 rt = mid - 1;187         }188 189         return ans;190     }191 192     inline void main(void)193     {194         for (int i = 1; i <= n; ++i)195             map[i] = s[i];196 197         std::sort(map + 1, map + 1 + n);198 199         for (int i = 1; i <= n; ++i)200             if (!tot || map[i] != map[tot])201                 map[++tot] = map[i];202 203         for (int i = 1; i <= n; ++i)204             s[i] = find(s[i]);205 206         h = tot;207     }208 }209 210 inline int solve(int l, int r)211 {212     int id = divideSequence::findStart(l), st, ret;213     214     if (id)215     {216         st = divideSequence::st[id];217         ret = divideSequence::rev[id][r];218     }219     else220         st = r + 1, ret = 0;221 222     if (st > r)223         st = r + 1;224     225     for (int i = l; i < st; ++i)226         ret += chairManTree::query(st, r, s[i]);227     228     binaryInsertTree::init();229 230     for (int i = l, sum = 0; i < st; ++i, ++sum)231     {232         ret += sum - binaryInsertTree::qry(s[i]);233         234         binaryInsertTree::add(s[i], 1);235     }236 237     return ret;238 }239 240 signed main(void)241 {242     n = fastRead::nextInt();243 244     for (int i = 1; i <= n; ++i)245         s[i] = fastRead::nextInt();246 247     preworkHash::main();248 249     chairManTree::main();250 251     divideSequence::main();252 253     m = fastRead::nextInt();254 255     for (int i = 1; i <= m; ++i)256     {257         int l = fastRead::nextInt();258         int r = fastRead::nextInt();259 260         l ^= lastAns;261         r ^= lastAns;262 263         printf("%d\n", lastAns = solve(l, r));264     }265 }

 

@Author: YouSiki

 

BZOJ 3744: Gty的妹子序列