zoukankan      html  css  js  c++  java
  • NOIP 2017 列队

    题目传送门

      传送点I

      传送点II

    题目大意

      (家喻户晓的题目应该不需要大意)

      (我之前咋把NOIP 2017打成了NOIP 2018,好绝望)

    Solution 1 Splay

      每行一颗Splay,没有动过的地方直接一段一个点。

      最后一列单独一颗Splay。

      暴力模拟即可。

    Soluion 2 Splay II

      我们考虑倒推。对于每个询问倒推出在第一次操作前时的位置。

      考虑每个出队操作对答案的影响。

      假设询问$(x, y)$,那么最后一列横坐标大于等于$x$的位置,横坐标都会加1.

      第$x$行,纵坐标大于等于$y$的位置,纵坐标都会加1.

      然后再把这个位置塞进$(x, y)$。

      然后暴力模拟就好了。

    Code

      1 /**
      2  * uoj
      3  * Problem#334
      4  * Accepted
      5  * Time: 4027ms
      6  * Memory: 25700k
      7  */
      8 #include <iostream>
      9 #include <cassert>
     10 #include <cstdlib>
     11 #include <cstdio>
     12 #ifndef WIN32
     13 #define Auto "%lld"
     14 #else
     15 #define Auto "%I64d"
     16 #endif
     17 using namespace std;
     18 typedef bool boolean;
     19 #define ll long long
     20 
     21 const int N = 3e5 + 5;
     22 
     23 typedef class SplayNode {
     24     public:
     25         int val, tg, id;
     26         SplayNode *ch[2];
     27         SplayNode *fa;
     28 
     29         SplayNode() {    }
     30 
     31         void pushDown() {
     32             for (int i = 0; i < 2; i++)
     33                 if (ch[i])
     34                     ch[i]->val += tg, ch[i]->tg += tg;
     35             tg = 0;
     36         }
     37 
     38         int which(SplayNode* p) {
     39             return p == ch[1];
     40         }
     41 }SplayNode;
     42 
     43 SplayNode pool[N << 1];
     44 SplayNode* top = pool;
     45 
     46 SplayNode* newnode(int val, int id) {
     47     top->val = val, top->id = id;
     48     top->ch[0] = top->ch[1] = top->fa = NULL;
     49     top->tg = 0;
     50     return top++;
     51 }
     52 
     53 SplayNode* stps[N];
     54 
     55 typedef class Splay {
     56     protected:
     57         void rotate(SplayNode* p) {
     58             SplayNode *fa = p->fa, *ffa = fa->fa;
     59             int df = fa->which(p);
     60             SplayNode* ls = p->ch[df ^ 1];
     61 
     62             p->fa = ffa;
     63             p->ch[df ^ 1] = fa;
     64             fa->fa = p;
     65             fa->ch[df] = ls;
     66             if (ls)
     67                 ls->fa = fa;
     68             if (ffa)
     69                 ffa->ch[ffa->which(fa)] = p;
     70         }
     71 
     72         void splay(SplayNode* p, SplayNode* fa) {
     73             SplayNode** st = stps;
     74             for (SplayNode* q = p; q; *(++st) = q, q = q->fa);
     75             for ( ; st != stps; (*st)->pushDown(), st--);
     76             for ( ; p->fa != fa; rotate(p))
     77                 if (p->fa->fa != fa)
     78                     rotate((p->fa->fa->which(p->fa) == p->fa->which(fa)) ? (p->fa) : (p));
     79             if (!fa)
     80                 rt = p;
     81         }
     82     public:
     83         SplayNode* rt;
     84 
     85         void insert(SplayNode*& p, SplayNode* fa, SplayNode* np) {
     86             if (!p) {
     87                 p = np, np->fa = fa;
     88                 return;
     89             }
     90             if (p->tg)
     91                 p->pushDown();
     92             insert(p->ch[np->val > p->val], p, np);
     93         }
     94 
     95         boolean less_bound(int x) {    // find the maximum number less than x and splay it
     96             SplayNode* ret = NULL, *p = rt, *q = NULL;
     97             while (p) {
     98                 q = p;
     99                 if (p->tg)
    100                     p->pushDown();
    101                 if (p->val < x)
    102                     ret = p, p = p->ch[1];
    103                 else
    104                     p = p->ch[0];
    105             }
    106             if (ret)
    107                 splay(ret, NULL);
    108             else if (q)
    109                 splay(q, NULL);
    110             return ret != NULL;
    111         }
    112 
    113         void remove(SplayNode* p) {
    114             splay(p, NULL);
    115             if (!p->ch[1]) {
    116                 rt = p->ch[0];
    117                 if (rt)
    118                     rt->fa = NULL;
    119                 return;
    120             }
    121 
    122             SplayNode* q = p->ch[1];
    123             while (q->ch[1])
    124                 q = q->ch[1];
    125             splay(q, p);
    126             q->ch[0] = p->ch[0];
    127             if (p->ch[0])
    128                 p->ch[0]->fa = q;
    129             rt = q;
    130         }
    131 
    132         SplayNode* findMax() {
    133             SplayNode* p = rt;
    134             while (p && p->ch[1]) {
    135                 if (p->tg)
    136                     p->pushDown();
    137                 p = p->ch[1];
    138             }
    139             if (p)
    140                 splay(p, NULL);
    141             return p;
    142         }
    143 
    144         void insert(SplayNode* p) {
    145             insert(rt, NULL, p);
    146             splay(p, NULL);
    147         }
    148         
    149         void getLis(SplayNode**& vs, SplayNode* p) {
    150             if (!p)
    151                 return;
    152             if (p->tg)
    153                 p->pushDown();
    154             *(vs++) = p;
    155             getLis(vs, p->ch[0]);
    156             getLis(vs, p->ch[1]);
    157         }
    158 }Splay;
    159 
    160 int n, m, q;
    161 Splay ls[N];        // maintain for (1, 1) - (n, m - 1)
    162 Splay rs;
    163 int xs[N], ys[N];
    164 ll res[N];
    165 
    166 inline void init() {
    167     scanf("%d%d%d", &n, &m, &q);
    168     for (int i = 1; i <= q; i++)
    169         scanf("%d%d", xs + i, ys + i);
    170 }
    171 
    172 int uf[N];
    173 
    174 int find(int x) {
    175     return (uf[x] == x) ? (x) : (uf[x] = find(uf[x])); 
    176 }
    177 
    178 inline void solve() {
    179     for (int i = 1; i <= q; i++)
    180         uf[i] = i;
    181 
    182     SplayNode *p;
    183     for (int i = q; i; i--) {
    184         int x = xs[i], y = ys[i];
    185         while ((p = rs.findMax()) && p->val == n)
    186             uf[find(p->id)] = i, rs.remove(p);
    187         if (rs.rt) {
    188             if (rs.less_bound(x)) {
    189                 p = rs.rt->ch[1];
    190                 if (p)
    191                     p->val++, p->tg++;
    192             } else
    193                 rs.rt->val++, rs.rt->tg++;
    194         }
    195         if (y == m) {
    196             rs.insert(newnode(x, i));
    197         } else {
    198             Splay& sp = ls[x];
    199             if (sp.rt) {
    200                 if (sp.less_bound(y)) {
    201                     p = sp.rt->ch[1];
    202                     if (p)
    203                         p->val++, p->tg++;
    204                 } else
    205                     sp.rt->val++, sp.rt->tg++;
    206             }
    207             while ((p = sp.findMax()) && p->val == m)
    208                 rs.insert(newnode(x, p->id)), sp.remove(p);
    209             sp.insert(newnode(y, i));
    210         }
    211     }
    212 
    213     SplayNode **pp, **pq;
    214     for (int i = 1; i <= n; i++) {
    215         pp = stps;
    216         ls[i].getLis(pp, ls[i].rt);
    217         for (pq = stps; pq != pp; pq++)
    218             res[(*pq)->id] = (i - 1) * 1ll * m + (*pq)->val;
    219     }
    220     pp = stps;
    221     rs.getLis(pp, rs.rt);
    222     for (pq = stps; pq != pp; pq++)
    223         res[(*pq)->id] = (*pq)->val * 1ll * m;
    224     for (int i = 1; i <= q; i++)
    225         printf(Auto"
    ", res[find(i)]);
    226 }
    227 
    228 int main() {
    229     init();
    230     solve();
    231     return 0;
    232 }
    Splay

    Solution 3 BIT

      考虑删掉的位置我们留下,如果我们知道所有按顺序被加进这一行的人,那么我们查找第$k$列的人相当于求第$k$大值。

      我们可以利用树状数组预处理出每一行除去最后一列,每个询问是第几个加入这一行的数(原来的数依次看做第一个,第二个,...)。

      然后开始处理询问。用类似的方法维护最后一列。

      这样可以算每次询问,最后一列被拿走的数,以及当且行被加入的数。

    Code

      1 /**
      2  * uoj
      3  * Problem#334
      4  * Accepted
      5  * Time: 1673ms
      6  * Memory: 32808b
      7  */
      8 #include <iostream>
      9 #include <cstdlib>
     10 #include <cstdio>
     11 #include <vector>
     12 #ifndef WIN32
     13 #define Auto "%lld"
     14 #else
     15 #define Auto "%I64d"
     16 #endif
     17 using namespace std;
     18 typedef bool boolean;
     19 
     20 template <typename T>
     21 void pfill(T* pst, const T* ped, T val) {
     22     for ( ; pst != ped; *(pst++) = val);
     23 }
     24 
     25 const int bzmax = 20;
     26 const int N = 3e5 + 5;
     27 
     28 typedef class IndexedTree {
     29     public:
     30         int *ar;
     31         int s;
     32 
     33         IndexedTree() {    }
     34         IndexedTree(int s):s(s) {
     35             ar = new int[(s + 1)];
     36             pfill(ar, ar + s + 1, 0);
     37         }
     38 
     39         void add(int idx, int val) {
     40             for ( ; idx <= s; idx += ((-idx) & idx))
     41                 ar[idx] += val;
     42         }
     43 
     44         int kth(int k) {
     45             int rt = 0, cur = 0;
     46             for (int b = (1 << (bzmax - 1)); b; b >>= 1)
     47                 if ((rt | b) <= s && cur + ar[rt | b] < k)
     48                     rt += b, cur += ar[rt | b];
     49             return rt + 1;
     50         }
     51 }IndexedTree;
     52 
     53 #define ll long long
     54 #define pii pair<int, int>
     55 #define fi first
     56 #define sc second
     57 
     58 int n, m, q, K;
     59 int rk[N];
     60 IndexedTree it;
     61 pii qs[N];
     62 vector<ll> lst;
     63 vector<ll> vs[N];
     64 vector<pii> ms[N];
     65 
     66 inline void init() {
     67     scanf("%d%d%d", &n, &m, &q);
     68     K = max(n, m) + q;
     69     it = IndexedTree(K);
     70     for (int i = 1; i <= q; i++) {
     71         scanf("%d%d", &qs[i].fi, &qs[i].sc);
     72         if (qs[i].sc < m)
     73             ms[qs[i].fi].push_back(pii(qs[i].sc, i));
     74     }
     75 }
     76 
     77 inline void solve() {
     78     for (int i = 1; i <= K; i++)
     79         it.add(i, 1);
     80     for (int i = 1; i <= n; i++) {
     81         for (vector<pii> :: iterator it = ms[i].begin(); it != ms[i].end(); it++)
     82             ::it.add(rk[it->sc] = ::it.kth(it->fi), -1);
     83         for (vector<pii> :: iterator it = ms[i].begin(); it != ms[i].end(); it++)
     84             ::it.add(rk[it->sc], 1);
     85     }
     86 
     87     ll res;
     88     for (int i = 1, x, y, p; i <= q; i++) {
     89         x = qs[i].fi, y = qs[i].sc;
     90         it.add(p = it.kth(x), -1);
     91         res = ((p <= n) ? (p * 1ll * m) : (lst[p - n - 1]));
     92         if (y < m) {
     93             vs[x].push_back(res);
     94             res = ((rk[i] <= m - 1) ? ((x - 1) * 1ll * m + rk[i]) : vs[x][rk[i] - m]);
     95         }
     96         lst.push_back(res);
     97         printf(Auto"
    ", res);
     98     }
     99 }
    100 
    101 int main() {
    102     init();
    103     solve();
    104     return 0;
    105 }
  • 相关阅读:
    1、Jenkins的安装与简单配置
    2、jenkins+svn自动发布和回滚
    关于kafka生产者相关监控指标的理解(未解决)
    Zabbix中获取各用户告警媒介分钟级统计
    2-4、配置Filebeat使用logstash
    JS基础 浏览器弹出的三种提示框(提示信息框、确认框、输入文本框)
    C# winform 托盘控件的使用
    c# 将两个表的有效数据合到一个表中
    C# 认识 接口
    let 和 var 定义变量的区别
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9789127.html
Copyright © 2011-2022 走看看