zoukankan      html  css  js  c++  java
  • BZOJ4552: [Tjoi2016&Heoi2016]排序

    题目大意

    给你一个$n$的排列,要求支持$m$次把$(l_i,r_i)$区间内数字升序或降序排,最后求某一个位置上的值。

    简要题解

    一开始维护$n$棵权值线段树,然后你需要支持split一棵线段树或者merge一棵线段树,用平衡树来维护区间就好了。

    关于线段树合并的复杂度分析。split复杂度显然和求第k大是一致的,而merge操作每次遍历到两个点都会删去一个,反正每次插入$log n$个节点,你删的点数总不会超过插入的点数啊。

    果然认真写然后认真思考然后肉眼查错效果要好很多,大概写完也没怎么调试,把空间开到$1e7$在食堂吃饭的时候随手交了一发然后和老高谈笑风生中AC了233.

    似乎跑的挺快(Rank5~)?

    还有就是,我线段树换写法了,感觉这种写法蛮好玩的,直接把merge和split写成节点类的成员函数,以前是数组党233

      1 //write by HuZhifeng(id : ichn(eumon) or sbit) @ 2017-02-20 周一 10:52 上午
      2 // It    attains    sublime
      3 // a-----------n----------d
      4 // yet performs common task.
      5 #include <bits/stdc++.h>
      6 using namespace std;
      7 namespace my_header {
      8 #define pb push_back
      9 #define mp make_pair
     10 #define pir pair<int, int>
     11 #define vec vector<int>
     12 #define pc putchar
     13 #define clr(t) memset(t, 0, sizeof t)
     14 #define pse(t, v) memset(t, v, sizeof t)
     15 #define bl puts("")
     16 #define wn(x) wr(x), bl
     17 #define ws(x) wr(x), pc(' ')
     18     const int INF = 0x3f3f3f3f;
     19     typedef long long LL;
     20     typedef double DB;
     21     inline char gchar() {
     22         char ret = getchar();
     23         for(; (ret == '
    ' || ret == '
    ' || ret == ' ') && ret != EOF; ret = getchar());
     24         return ret; }
     25     template<class T> inline void fr(T &ret, char c = ' ', int flg = 1) {
     26         for(c = getchar(); (c < '0' || '9' < c) && c != '-'; c = getchar());
     27         if (c == '-') { flg = -1; c = getchar(); }
     28         for(ret = 0; '0' <= c && c <= '9'; c = getchar())
     29             ret = ret * 10 + c - '0';
     30         ret = ret * flg; }
     31     inline int fr() { int t; fr(t); return t; }
     32     template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); }
     33     template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); }
     34     template<class T> inline char wr(T a, int b = 10, bool p = 1) {
     35         return a < 0 ? pc('-'), wr(-a, b, 0) : (a == 0 ? (p ? pc('0') : p) : 
     36             (wr(a/b, b, 0), pc('0' + a % b)));
     37     }
     38     template<class T> inline void wt(T a) { wn(a); }
     39     template<class T> inline void wt(T a, T b) { ws(a), wn(b); }
     40     template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); }
     41     template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); }
     42     template<class T> inline T gcd(T a, T b) {
     43         return b == 0 ? a : gcd(b, a % b); }
     44     template<class T> inline T fpw(T b, T i, T _m, T r = 1) {
     45         for(; i; i >>= 1, b = b * b % _m)
     46             if(i & 1) r = r * b % _m;
     47         return r; }
     48 };
     49 using namespace my_header;
     50  
     51  
     52 const int MAXN = 1e7 + 100;
     53 #define SN SegNode
     54 #define lc ch[0]
     55 #define rc ch[1]
     56 struct SegNode {
     57     SegNode *ch[2];
     58     int s;
     59     void update() {
     60         s = (lc ? lc->s : 0) + (rc ? rc->s : 0);
     61     }
     62     int kth(int l, int r, int k) {
     63         if (l == r)
     64             return l;
     65         int m = (l + r) >> 1;
     66         int ls = lc ? lc->s : 0;
     67         if (k <= ls)
     68             return lc->kth(l, m, k);
     69         return rc->kth(m + 1, r, k - ls);
     70     }
     71     void insert(int, int, int);
     72     pair<SegNode*, SegNode*> split(int, int, int);
     73     SegNode* merge(int, int, SegNode*);
     74 } node_pool[MAXN], *loc = node_pool;
     75 SegNode* newSegNode() {
     76     return loc++;
     77 }
     78  
     79 pair<SegNode*, SegNode*> SegNode::split(int l, int r, int k) {
     80     if (k == 0)
     81         return make_pair((SegNode*)NULL, this);
     82     if (l == r || k == this->s)
     83         return make_pair(this, (SegNode*)NULL);
     84     int m = (l + r) >> 1;
     85     int ls = lc ? lc->s : 0;
     86     if (k <= ls) {
     87         pair<SegNode*, SegNode*> res = lc->split(l, m, k);
     88         SegNode* nr = newSegNode();
     89         nr->lc = res.first;
     90         nr->rc = NULL;
     91         nr->update();
     92         this->lc = res.second;
     93         this->update();
     94         return make_pair(nr, this);
     95     } else {
     96         pair<SegNode*, SegNode*> res = rc->split(m + 1, r, k - ls);
     97         this->rc = res.first;
     98         this->update();
     99         SegNode* nr = newSegNode();
    100         nr->lc = NULL;
    101         nr->rc = res.second;
    102         nr->update();
    103         return make_pair(this, nr);
    104     }
    105 }
    106  
    107 SegNode* SegNode::merge(int l, int r, SegNode* x) {
    108     if (l != r && x != NULL) {
    109         int m = (l + r) >> 1;
    110         if (!this->lc)
    111             this->lc = x->lc;
    112         else {
    113             if (x->lc)
    114                 this->lc->merge(l, m, x->lc);
    115         }
    116         if (!this->rc)
    117             this->rc = x->rc;
    118         else {
    119             if (x->rc)
    120                 this->rc->merge(m + 1, r, x->rc);
    121         }
    122         this->update();
    123     }
    124     return this;
    125 }
    126  
    127 set<pair<int, pair<int, int> > > status;
    128 set<pair<int, pair<int, int> > >::iterator tmp, tmp2;
    129 pair<int, pair<int, int> > rec;
    130 SegNode* root[MAXN];
    131  
    132 void SegNode::insert(int l, int r, int v) {
    133     if (l == r)
    134         s = 1;
    135     else {
    136         int m = (l + r) >> 1;
    137         if (v <= m) {
    138             if (!this->lc)
    139                 this->lc = newSegNode();
    140             this->lc->insert(l, m, v);
    141         } else {
    142             if (!this->rc)
    143                 this->rc = newSegNode();
    144             this->rc->insert(m + 1, r, v);
    145         }
    146         this->update();
    147     }
    148 }
    149  
    150 int n, m;
    151 // 沉下心来 细节是魔鬼 通过思考 战胜魔鬼!
    152 void split(int p, int tp) {
    153     pair<SegNode*, SegNode*> res;
    154     tmp = status.upper_bound(make_pair(p, make_pair(0, 0)));
    155     if (tmp != status.begin() && tmp->first != p)
    156         --tmp;
    157     SegNode* nr = newSegNode();
    158     if (tmp->second.second == 0) {
    159         res = root[tmp->first]->split(1, n, p - tmp->first + tp);
    160         root[tmp->first] = res.first;
    161         nr->merge(1, n, res.second);
    162     } else {
    163         res = root[tmp->first]->split(1, n, tmp->second.first - p + tmp->first - tp);
    164         root[tmp->first] = res.second;
    165         nr->merge(1, n, res.first);
    166     }
    167     rec = *tmp;
    168     status.erase(tmp);
    169     if (root[rec.first])
    170         status.insert(make_pair(rec.first, make_pair(root[rec.first]->s, rec.second.second)));
    171     if (nr) {
    172         rec = *status.insert(make_pair(p + tp, make_pair(nr->s, rec.second.second))).first;
    173         if (rec.second.first == 0) {
    174             status.erase(rec);
    175         } else {
    176             root[rec.first] = nr;
    177         }
    178     }
    179 }
    180  
    181 int main() {
    182 #ifdef lol
    183     freopen("4552.in", "r", stdin);
    184     freopen("4552.out", "w", stdout);
    185 #endif
    186  
    187     fr(n, m);
    188     for (int i = 1; i <= n; ++i) {
    189         root[i] = newSegNode();
    190         root[i]->insert(1, n, fr());
    191         status.insert(make_pair(i, make_pair(1, 0)));
    192     }
    193     while (m--) {
    194         int op, l, r;
    195         fr(op, l, r);
    196         //for (auto &&i : status) {
    197         //  wt(i.first, i.second.first, i.second.second);
    198         //}
    199         //puts("");
    200         split(l, 0);
    201         split(r, 1);
    202         //for (auto &&i : status) {
    203         //  wt(i.first, i.second.first, i.second.second);
    204         //}
    205         //puts("");
    206         tmp2 = tmp = status.lower_bound(make_pair(l, make_pair(0, 0)));
    207         for (++tmp2; tmp2 != status.end() && tmp2->first <= r; ++tmp2) {
    208             root[l]->merge(1, n, root[tmp2->first]);
    209             root[tmp2->first] = NULL;
    210         }
    211         rec = *tmp;
    212         status.erase(tmp, tmp2);
    213         status.insert(make_pair(rec.first, make_pair(root[l]->s, op)));
    214     }
    215     //for (auto &&i : status) {
    216     //      wt(i.first, i.second.first, i.second.second);
    217     //  }
    218     //  puts("");
    219     //  
    220     fr(m);
    221     tmp = status.upper_bound(make_pair(m, make_pair(0, 0)));
    222     if (tmp != status.begin() && tmp->first != m)
    223         --tmp;
    224     m -= tmp->first;
    225     wt(root[tmp->first]->kth(1, n, tmp->second.second ? tmp->second.first - m : (m + 1)));
    226  
    227     return 0;
    228 }
  • 相关阅读:
    博客园cnblogs for win8 托管到GitHub开源
    html5 canvas 画图表
    回文数
    SpringBoot+logback实现按业务输出日志到不同的文件
    Class.forName() 与 ClassLoader.loadClass()的区别
    Easypoi实现单模板生成多页word文档
    普通Java项目中使用Sl4j+Log4j2打印日志
    SpringBoot集成JWT
    Java8_Lambda表达式
    SpringBoot自定义Condition注解
  • 原文地址:https://www.cnblogs.com/ichn/p/6421013.html
Copyright © 2011-2022 走看看