Orz zzd大神太强啦!
解:首先发现几个性质:如果把区间还原到原序列上的话,可以发现这些区间要么包含,要么相离。不存在相交。
然后发现如果区间a包含区间b,那么最后剩下来的人,a一定不小于b。又发现最优决策要么是0,要么是在某个极小的区间内。
然后我们发现这TM不就可以建出一棵树来么?枚举叶节点然后树上倍增找到最多能胜场数,然后取max即可。
怎么搞出原序列上的区间来呢?我先想到树状数组(????),然后搞了一个小时还不会定位区间,爆0了。
后来发现splay可以随便水......
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 3 const int N = 100010; 4 5 struct Edge { 6 int nex, v; 7 }edge[N << 1]; int tp; 8 9 struct Node { 10 int x, y, l, r, val; 11 inline bool operator <(const Node &w) const { 12 if(l != w.l) return l < w.l; 13 return r > w.r; 14 } 15 }node[N]; 16 17 int a[N], stk[N], top, root, n, m, K, e[N], pw[N], d[N], fa[N]; 18 int s[N][2], faa[N][20], siz[N], lc[N], rc[N], tot, ST[N][20]; 19 20 inline void add(int x, int y) { 21 tp++; 22 edge[tp].v = y; 23 edge[tp].nex = e[x]; 24 e[x] = tp; 25 return; 26 } 27 28 inline void pushup(int x) { 29 siz[x] = siz[s[x][0]] + siz[s[x][1]] + 1; 30 if(!fa[x]) root = x; 31 return; 32 } 33 34 inline void pushdown(int x) { 35 return; 36 } 37 38 inline void rotate(int x) { 39 int y = fa[x]; 40 int z = fa[y]; 41 bool f = (s[y][1] == x); 42 43 fa[x] = z; 44 if(z) { 45 s[z][s[z][1] == y] = x; 46 } 47 s[y][f] = s[x][!f]; 48 if(s[x][!f]) { 49 fa[s[x][!f]] = y; 50 } 51 s[x][!f] = y; 52 fa[y] = x; 53 54 pushup(y); 55 return; 56 } 57 58 inline void splay(int x, int g = 0) { 59 int y = x; 60 stk[top = 1] = y; 61 while(fa[y]) { 62 y = fa[y]; 63 stk[++top] = y; 64 } 65 while(top) { 66 pushdown(stk[top]); 67 top--; 68 } 69 y = fa[x]; 70 int z = fa[y]; 71 while(y != g) { 72 if(z != g) { 73 (s[y][1] == x) ^ (s[z][1] == y) ? 74 rotate(x) : rotate(y); 75 } 76 rotate(x); 77 y = fa[x]; 78 z = fa[y]; 79 } 80 pushup(x); 81 return; 82 } 83 84 inline int np(int f, int l, int r) { 85 int x = ++tot; 86 fa[x] = f; 87 lc[x] = l; 88 rc[x] = r; 89 siz[x] = 1; 90 return x; 91 } 92 93 inline int getPbyR(int k) { 94 int p = root; 95 k++; 96 while(1) { 97 if(k <= siz[s[p][0]]) { 98 p = s[p][0]; 99 } 100 else if(k == siz[s[p][0]] + 1) { 101 break; 102 } 103 else { 104 k -= siz[s[p][0]] + 1; 105 p = s[p][1]; 106 } 107 } 108 splay(p); 109 return p; 110 } 111 112 int build(int f, int l, int r) { 113 if(l == r) { 114 return np(f, l, r); 115 } 116 int mid = (l + r) >> 1; 117 int x = np(f, mid, mid); 118 if(l < mid) s[x][0] = build(x, l, mid - 1); 119 if(mid < r) s[x][1] = build(x, mid + 1, r); 120 pushup(x); 121 return x; 122 } 123 124 inline int getL(int p = root) { 125 pushdown(p); 126 while(s[p][0]) { 127 p = s[p][0]; 128 pushdown(p); 129 } 130 return p; 131 } 132 133 inline int getR(int p = root) { 134 pushdown(p); 135 while(s[p][1]) { 136 p = s[p][1]; 137 pushdown(p); 138 } 139 return p; 140 } 141 142 inline void merge(int x, int l, int r) { 143 lc[x] = l; 144 rc[x] = r; 145 siz[x] = 1; 146 s[x][0] = s[x][1] = 0; 147 return; 148 } 149 150 inline void prework() { 151 for(int i = 2; i <= n; i++) { 152 pw[i] = pw[i >> 1] + 1; 153 } 154 for(int i = 1; i < n; i++) ST[i][0] = a[i]; 155 for(int j = 1; j <= pw[n]; j++) { 156 for(int i = 1; i + (1 << j) - 1 <= n; i++) { 157 ST[i][j] = std::max(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]); 158 } 159 } 160 return; 161 } 162 163 inline void prework2() { 164 for(int j = 1; j <= pw[m]; j++) { 165 for(int i = 1; i <= m; i++) { 166 faa[i][j] = faa[faa[i][j - 1]][j - 1]; 167 } 168 } 169 return; 170 } 171 172 inline int getPos(int x) { 173 int t = pw[m]; 174 while(t >= 0) { 175 if(faa[x][t] && node[faa[x][t]].val <= K) { 176 x = faa[x][t]; 177 } 178 t--; 179 } 180 return x; 181 } 182 183 inline int getMax(int x, int y) { 184 int t = pw[y - x + 1]; 185 return std::max(ST[x][t], ST[y - (1 << t) + 1][t]); 186 } 187 /* 188 5 3 3 189 1 0 2 4 190 1 3 191 0 1 192 0 1 193 */ 194 int main() { 195 196 scanf("%d%d%d", &n, &m, &K); 197 for(int i = 1; i < n; i++) { 198 scanf("%d", &a[i]); 199 } 200 for(int i = 1; i <= m; i++) { 201 scanf("%d%d", &node[i].x, &node[i].y); 202 node[i].x++; 203 node[i].y++; 204 } 205 /// input OVER 206 207 prework(); 208 root = build(0, 0, n + 1); 209 210 for(int i = 1; i <= m; i++) { 211 int L = getPbyR(node[i].x - 1); 212 int R = getPbyR(node[i].y + 1); 213 splay(L, R); 214 int l = getL(s[L][1]), r = getR(s[L][1]); 215 node[i].l = lc[l]; 216 node[i].r = rc[r]; 217 node[i].val = getMax(node[i].l, node[i].r - 1); 218 merge(s[L][1], node[i].l, node[i].r); 219 pushup(L); 220 pushup(R); 221 } 222 223 std::sort(node + 1, node + m + 1); 224 top = 0; 225 for(int i = 1; i <= m; i++) { 226 while(top && node[i].l > node[stk[top]].r) { 227 top--; 228 } 229 if(top) { 230 add(stk[top], i); 231 faa[i][0] = stk[top]; 232 } 233 stk[++top] = i; 234 } 235 236 prework2(); 237 for(int i = 1; i <= m; i++) { 238 d[i] = d[faa[i][0]] + 1; 239 } 240 241 int ans = 0, pos = 1; 242 for(int x = 1; x <= m; x++) { 243 if(e[x] || node[x].val > K) continue; 244 int t = getPos(x); 245 t = d[x] - d[t] + 1; 246 if(t > ans) { 247 ans = t; 248 pos = node[x].l; 249 } 250 else if(t == ans) { 251 pos = std::min(pos, node[x].l); 252 } 253 } 254 255 printf("%d ", pos - 1); 256 return 0; 257 }