军团指挥官(权限题)

Orz zzd大神太强啦!

解:首先发现几个性质:如果把区间还原到原序列上的话,可以发现这些区间要么包含,要么相离。不存在相交。

然后发现如果区间a包含区间b,那么最后剩下来的人,a一定不小于b。又发现最优决策要么是0,要么是在某个极小的区间内。

然后我们发现这TM不就可以建出一棵树来么?枚举叶节点然后树上倍增找到最多能胜场数,然后取max即可。

怎么搞出原序列上的区间来呢?我先想到树状数组(????),然后搞了一个小时还不会定位区间,爆0了。

后来发现splay可以随便水......

 

  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\n", pos - 1);
256     return 0;
257 }
AC代码

 

posted @ 2019-03-24 15:24  huyufeifei  阅读(236)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

ReadEra 阅读书籍

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜