BZOJ 3744: Gty的妹子序列
3744: Gty的妹子序列
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 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
1 4 2 3
1
2 4
Sample Output
2
HINT
Source
╮(╯▽╰)╭ 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 binaryInsertTree 100 { 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 divideSequence 126 { 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 else 142 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 preworkHash 172 { 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 else 186 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 else 220 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