• BZOJ3110 [ZJOI2013] K大数查询


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3110

    Description

    有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
    如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

    Input

    第一行N,M
    接下来M行,每行形如1 a b c或2 a b c

    Output

    输出每个询问的结果

    Orz hzwer!黄学长太神啦!

    去翻题解,看到可以用树状数组套主席树,然而我不理解其中奥妙,只能打权值线段树套区间线段树

    注意题意,在一个“位置”上可能会有多个数

    然而求的是区间第K大,不是排名为K的数,一个位置上可能有多个数,这样一个区间内有多少个数根本不知道

    结果去黄学长博客,才注意到“1操作中abs(c)<=N”,而且数据没有负数

    于是就可以将插入的数 c 转换为 n - c + 1,然后就可以将区间第K大转换为查询区间排名为K的数

    放学后将内层线段树改为指针版本,速度没有变快反而慢了几十到一百毫秒,指针写得丑也呵呵哒

    下图是数组版代码的评测结果,代码是奇丑无比的指针版的

    另外貌似结构体比数组快?

    2016.3.8 update: KPM加强数据,下面的代码被叉,新的题解见这里:http://www.cnblogs.com/jimzeng/p/bzoj3110_2.html

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #define rep(i,l,r) for(int i=l; i<=r; i++)
     6 #define clr(x,y) memset(x,y,sizeof(x))
     7 using namespace std;
     8 const int maxn = 50010;
     9 inline int read(){
    10     int ans = 0, f = 1;
    11     char c = getchar();
    12     for(; !isdigit(c); c = getchar())
    13     if (c == '-') f = -1;
    14     for(; isdigit(c); c = getchar())
    15     ans = ans * 10 + c - '0';
    16     return ans * f;
    17 }
    18 struct Node{
    19     int s,t; Node *ls,*rs;
    20     inline void maintain(){
    21         s = ls->s + rs->s;
    22     }
    23 }t[20000010],*pt = t,*null,*rt[maxn<<2];
    24 int n,m,f,a,b,c;
    25 inline Node* newnode(){
    26     pt->s = pt->t = 0; pt->ls = pt->rs = null;
    27     return pt++;
    28 }
    29 inline void init(){
    30     null = newnode();
    31     rep(i,1,n<<2) rt[i] = null;
    32 }
    33 inline void pushdown(Node *p,int l,int r){
    34     if (!p->t || l == r) return;
    35     if (p->ls == null) p->ls = newnode();
    36     if (p->rs == null) p->rs = newnode();
    37     p->ls->t += p->t; p->rs->t += p->t;
    38     int mid = (l + r) >> 1;
    39     p->ls->s += (mid - l + 1) * p->t;
    40     p->rs->s += (r - mid) * p->t;
    41     p->t = 0;
    42 }
    43 void modify(int u,int v,Node *&p,int l,int r){
    44     if (p == null) p = newnode();
    45     pushdown(p,l,r);
    46     if (u == l && v == r){
    47         p->s += (r - l + 1);
    48         p->t ++; return;
    49     }
    50     int mid = (l + r) >> 1;
    51     if (v <= mid) modify(u,v,p->ls,l,mid);
    52     else if (u > mid) modify(u,v,p->rs,mid+1,r);
    53     else{
    54         modify(u,mid,p->ls,l,mid);
    55         modify(mid+1,v,p->rs,mid+1,r);
    56     }
    57     p->maintain();
    58 }
    59 int query(int u,int v,Node *p,int l,int r){
    60     if (p == null) return 0;
    61     pushdown(p,l,r);
    62     if (u == l && v == r) return p->s;
    63     int mid = (l + r) >> 1;
    64     if (v <= mid) return query(u,v,p->ls,l,mid);
    65     else if (u > mid) return query(u,v,p->rs,mid+1,r);
    66     else return query(u,mid,p->ls,l,mid) + query(mid+1,v,p->rs,mid+1,r);
    67 }
    68 void insert(){
    69     int k = 1, l = 1, r = n;
    70     while (l < r){
    71         int mid = (l + r) >> 1;
    72         modify(a,b,rt[k],1,n);
    73         if (c <= mid) r = mid, k <<= 1;
    74         else l = mid + 1, k = k << 1 | 1;
    75     }
    76     modify(a,b,rt[k],1,n);
    77 }
    78 int solve(){
    79     int k = 1, l = 1, r = n;
    80     while (l < r){
    81         int mid = (l + r) >> 1;
    82         int t = query(a,b,rt[k<<1],1,n);
    83         if (t >= c) r = mid, k <<= 1;
    84         else l = mid + 1, k = k << 1 | 1, c -= t;
    85     }
    86     return l;
    87 }
    88 int main(){
    89     n = read(); m = read(); init();
    90     rep(i,1,m){
    91         f = read(); a = read(); b = read(); c = read();
    92         if (f == 1){
    93             c = n - c + 1; insert();
    94         }
    95         else printf("%d
    ",n - solve() + 1);
    96     }
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    GAE 1.5.1 SDK Prerelease
    GAE 1.5.1 SDK Prerelease
    SVN 分支更新与合并
    暂时告别 CSDN 博客,移居 GAE(http://88250.b3log.org)
    暂时告别 CSDN 博客,移居 GAE(http://88250.b3log.org)
    NetBeans 时事通讯(刊号 # 152 Jun 22, 2011)
    NetBeans 时事通讯(刊号 # 152 Jun 22, 2011)
    NetBeans 时事通讯(刊号 # 151 Jun 15, 2011)
    SVN 分支更新与合并
    NetBeans 时事通讯(刊号 # 151 Jun 15, 2011)
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj3110.html
Copyright © 2020-2023  润新知