• ZJOI 2013 K大数查询


    题目链接bzoj点我:-) 洛谷点我:-)
    题目描述
    有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

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

    输出格式
    输出每个询问的结果

    数据说明
    N,M<=50000,N,M<=50000
    a<=b<=N
    1操作中abs(c)<=N
    2操作中c<=Maxlongint

    思路
    本题有多法可解,比如权值线段树套区间线段树,线段树套splay,线段树套主席树,树状数组套线段树,整体二分,CDQ分治等
    介绍最简单的权值线段树套区间线段树:
    外层即以权值为线段树区间,内层以原区间为线段树区间,树套树。
    1操作为外层线段树单点修改,内层线段树区间修改
    2操作为外层线段树区间修改,内层线段树区间修改

    比较卡空间,需把内层线段树动态开点。并且注意离散化和long long

    感想
    第一次写树套树,怎么这么卡我空间。。。洛谷不让过,硬是讲我MLE,bzoj较为善良让我过了,
    但是。。居然有17000+ms。。莫非我天生自带大常数?!!

    代码

     1 //miaomiao 2017.2.11
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<map>
     5 
     6 using namespace std;
     7 
     8 #define LL long long
     9 #define mid ((L+R)>>1)
    10 #define For(i, a, b) for(int i = (a); i <= (int)(b); i++)
    11 #define N (50000+1)
    12 #define M (12000000+1)
    13 
    14 struct node{
    15     int op, a, b;
    16     LL c;
    17 }qus[N];
    18 
    19 int lc[M], rc[M], root[N<<4], xn, num[N], val[N], ql, qr, cnt, mn;
    20 LL sum[M], add[M];
    21 map<LL, int> ms;
    22 
    23 void modify(int &o, int L, int R){
    24     if(!o) o = ++cnt;
    25     if(ql <= L && R <= qr){add[o]++; sum[o]+=(R-L+1); return;}
    26 
    27     if(ql <= mid) modify(lc[o], L, mid); if(qr > mid) modify(rc[o], mid+1, R);
    28     sum[o] = sum[lc[o]]+sum[rc[o]]+add[o]*(R-L+1);
    29 }
    30 
    31 LL query(int &o, int L, int R, LL Add){
    32     if(!o) o = ++cnt;
    33     if(ql <= L && qr >= R) return sum[o]+Add*(R-L+1);
    34     LL ret = 0;
    35     if(ql <= mid) ret += query(lc[o], L, mid, Add+add[o]);
    36     if(qr > mid) ret += query(rc[o], mid+1, R, Add+add[o]);
    37     return ret;
    38 }
    39 
    40 int main(){
    41     int n, m, now, L, R;
    42     LL c, t;
    43     scanf("%d%d", &n, &m);
    44     For(i, 1, m){
    45         scanf("%d%d%d%lld", &qus[i].op, &qus[i].a, &qus[i].b, &qus[i].c);
    46         if(qus[i].op == 1) num[++xn] = qus[i].c;
    47     }
    48     sort(num+1, num+xn+1);
    49     For(i, 1, xn)
    50         if(num[i] != num[i-1] || i==1) ms[num[i]] = ++mn, val[mn] = num[i];
    51 
    52     For(i, 1, m){
    53         ql = qus[i].a; qr = qus[i].b; c = qus[i].c;
    54         now = 1; L = 1; R = n;
    55         if(qus[i].op == 1){
    56             c = ms[c];
    57             while(true){
    58                 modify(root[now], 1, n);
    59                 if(L == R) break;
    60                 if(c <= mid) now = now<<1, R = mid;
    61                 else now = now<<1|1, L = mid+1;
    62             }
    63         }else{
    64             while(L < R){
    65                 t = query(root[now<<1|1], 1, n, 0);
    66                 if(t >= c) L = mid+1, now = now<<1|1;    
    67                 else R = mid, now = now<<1, c -= t;
    68             }
    69             printf("%d
    ", val[L]);
    70         }
    71     }
    72 
    73     return 0;
    74 }
     
  • 相关阅读:
    获取URL的name值 getUrl(url,name) 传入url和key 得到key对应的value
    封装GetQueryString()方法来获取URL的value值
    判断设备
    RecyclerView 加点击事件
    SparseArray,SparseBooleanArray和SparseIntArray
    内存泄漏监测-LeakCanary
    StrictMode
    数据结构-线性结构
    程序设计语言基础-知识点
    数据结构-概念
  • 原文地址:https://www.cnblogs.com/miaomiao1220/p/6642337.html
Copyright © 2020-2023  润新知