zoukankan      html  css  js  c++  java
  • [BZOJ 3223 & Tyvj 1729]文艺平衡树 & [CodeVS 3243]区间翻转

    题目不说了,就是区间翻转

    传送门:BZOJ 3223 和 CodeVS 3243

    第一道题中是1~n的区间翻转,而第二道题对于每个1~n还有一个附加值

    实际上两道题的思路是一样的,第二题把值对应到位置就行了

    这里我们用伸展树来解决,但其中用到了线段树中的标记思想

    对于一个长度的为n的序列,我们把它的每一位向后移动一位,即1~n → 2~n+1,然后再在序列前后分别补上一位:1和n+2。所以我们需要建立一颗节点数为n+2的伸展树,而原序列中的1~n位分别对应新序列中的2~n+1位。

    对于每次询问的l和r,实际上就是l+1和r+1,首先找到l+1前一位对应的元素和r+1后一位对应的元素,即l和r+2分别对应的元素的序号。然后将l对应元素通过splay操作旋转到根节点,将r+2对应元素旋转到根节点的右儿子,由排序二叉树的性质可知,r+2的左儿子就是序列l+1~r+1,也就是询问中需要翻转的区间。对r+2的左儿子直接打上标记,在之后找元素序号的时候要记得把标记下传,同时用swap操作来达到翻转的目的。

    splay操作和rotate操作在此不赘述。

    最后输出的时候,同样查找2~n+1对应的元素序号,将得到的值减1还原,对于CodeVS 3243就再套一个值输出即可。

    这里给出BZOJ 3223的代码。

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cstring>
      6 #include <cmath>
      7 #include <ctime>
      8 #include <queue>
      9 #include <string>
     10 #include <map>
     11 typedef long long ll;
     12 using namespace std;
     13 const int MAXN = 100020;
     14 int n, m;
     15 int root;
     16 int son[MAXN][2], fa[MAXN], lazy[MAXN], siz[MAXN];
     17  
     18 inline int gi() {
     19     char c;
     20     int sum = 0, f = 1;
     21     c = getchar();
     22     while (c < '0' || c > '9') {
     23         if (c == '-')
     24             f = -1;
     25         c = getchar();
     26     }
     27     while (c >= '0' && c <= '9') {
     28         sum = sum * 10 + c - '0';
     29         c = getchar();
     30     }
     31     return sum * f;
     32 }
     33  
     34 void build(int l, int r, int f) {
     35     if (l > r)
     36         return;
     37     if (l == r) {
     38         siz[l] = 1;
     39         fa[l] = f;
     40         son[f][l > f] = l;
     41         return;
     42     }
     43     int mid = (l + r) >> 1;
     44     build(l, mid - 1, mid);
     45     build(mid + 1, r, mid);
     46     siz[mid] = siz[son[mid][0]] + siz[son[mid][1]] + 1;
     47     fa[mid] = f;
     48     son[f][mid > f] = mid;
     49 }
     50  
     51 void pushdown(int o) {
     52     swap(son[o][0], son[o][1]);
     53     lazy[son[o][0]] ^= 1;
     54     lazy[son[o][1]] ^= 1;
     55     lazy[o] = 0;
     56 }
     57  
     58 int find(int o, int p) {
     59     if (lazy[o])
     60         pushdown(o);
     61     int l = son[o][0];
     62     int r = son[o][1];
     63     if (siz[l] + 1 == p)
     64         return o;
     65     if (siz[l] >= p)
     66         return find(l, p);
     67     else
     68         return find(r, p - siz[l] - 1);
     69 }
     70  
     71 void rotate(int x, int &to) {
     72     int l, r;
     73     int f = fa[x];
     74     int ff = fa[f];
     75     l = son[f][0] == x ? 0 : 1;
     76     r = l ^ 1;
     77     if (f == to)
     78         to = x;
     79     else
     80         son[ff][son[ff][1] == f] = x;
     81     fa[x] = fa[f];
     82     fa[f] = x;
     83     fa[son[x][r]] = f;
     84     son[f][l] = son[x][r];
     85     son[x][r] = f;
     86     siz[f] = siz[son[f][0]] + siz[son[f][1]] + 1;
     87     siz[x] = siz[son[x][0]] + siz[son[x][1]] + 1;
     88 }
     89  
     90 void splay(int x, int &to) {
     91     while (x != to) {
     92         int f = fa[x];
     93         int ff = fa[f];
     94         if (f != to) {
     95             if ((son[f][0] == x) ^ (son[ff][0] == f))
     96                 rotate(x, to);
     97             else
     98                 rotate(f, to);
     99         }
    100         rotate(x, to);
    101     }
    102 }
    103  
    104 void reserve(int l, int r) {
    105     int x = find(root, l);
    106     int y = find(root, r + 2);
    107     splay(x, root);
    108     splay(y, son[x][1]);
    109     lazy[son[y][0]] ^= 1;
    110 }
    111  
    112 int main() {
    113     n = gi();
    114     m = gi();
    115     build(1, n + 2, 0);
    116     root = (n + 3) >> 1;
    117     for (int i = 1; i <= m; i++) {
    118         int l = gi();
    119         int r = gi();
    120         reserve(l, r);
    121     }
    122     for (int i = 2; i <= n + 1; i++)
    123         printf("%d ", find(root, i) - 1);
    124     return 0;
    125 }
  • 相关阅读:
    hdu1754:I Hate It
    hdu1166
    bzoj1642:挤奶时间
    线段树
    bzoj1699:排队
    bzoj3438: 小M的作物
    bzoj2127: happiness
    bzoj2768[JLOI2010]冠军调查
    bzoj1070[SCOI2007]修车
    bzoj1305[CQOI2009]dance跳舞
  • 原文地址:https://www.cnblogs.com/LRH-5574/p/5651498.html
Copyright © 2011-2022 走看看