zoukankan      html  css  js  c++  java
  • BZOJ K大数查询(分治)(Zjoi2013)

    题目链接: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

    输出每个询问的结果

     
    题目大意:略。
    思路:分治答案。答案范围[-n, n],从前往后扫描,若是插入操作且c>mid,则把线段树中区间[a, b]加一,并置为为类别1;否则置为类别0。若是询问操作,若目前线段树中区间[a, b]的和小于等于c,则置为类别1;否则置为类别0,并把c减去区间[a, b]的和。然后分治处理,其中类别0中,答案范围为[-n, mid];类别1中,答案范围为[mid + 1, n]。按类别排序后,两个区间之间互不影响。时间复杂度为O(nlognlogn)。
     
    代码(4940MS):
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 using namespace std;
      6 typedef long long LL;
      7 
      8 const int MAXN = 50010;
      9 const int MAXT = MAXN << 2;
     10 
     11 int sum[MAXT];
     12 int add[MAXT];
     13 bool clr[MAXT];
     14 
     15 #define ll (x << 1)
     16 #define rr (ll | 1)
     17 #define mid ((l + r) >> 1)
     18 void initTree() {
     19     sum[1] = add[1] = 0;
     20     clr[1] = true;
     21 }
     22 
     23 void pushdown(int x, int l, int r) {
     24     if(clr[x]) {
     25         clr[ll] = clr[rr] = true;
     26         sum[ll] = sum[rr] = add[ll] = add[rr] = 0;
     27         clr[x] = false;
     28     }
     29     if(add[x]) {
     30         sum[ll] += (mid - l + 1) * add[x];
     31         add[ll] += add[x];
     32         sum[rr] += (r - mid) * add[x];
     33         add[rr] += add[x];
     34         add[x] = 0;
     35     }
     36 }
     37 
     38 void maintain(int x) {
     39     sum[x] = sum[ll] + sum[rr];
     40 }
     41 
     42 void modify(int x, int l, int r, int a, int b) {
     43     if(a <= l && r <= b) {
     44         add[x]++;
     45         sum[x] += (r - l + 1);
     46     } else {
     47         pushdown(x, l, r);
     48         if(a <= mid) modify(ll, l, mid, a, b);
     49         if(mid < b) modify(rr, mid + 1, r, a, b);
     50         maintain(x);
     51     }
     52 }
     53 
     54 int query(int x, int l, int r, int a, int b) {
     55     if(a <= l && r <= b) {
     56         return sum[x];
     57     } else {
     58         pushdown(x, l, r);
     59         int res = 0;
     60         if(a <= mid) res += query(ll, l, mid, a, b);
     61         if(mid < b) res += query(rr, mid + 1, r, a, b);
     62         return res;
     63     }
     64 }
     65 #undef mid
     66 
     67 struct Node {
     68     int op, id, a, b, c, v;
     69     void read(int i) {
     70         id = i;
     71         scanf("%d%d%d%d", &op, &a, &b, &c);
     72     }
     73     bool operator < (const Node &rhs) const {
     74         if(v != rhs.v) return v < rhs.v;
     75         return id < rhs.id;
     76     }
     77 } p[MAXN];
     78 int ans[MAXN];
     79 int n, m;
     80 
     81 void work(int a, int b, int l, int r) {
     82     if(l > r) return ;
     83     if(a == b) {
     84         for(int i = l; i <= r; ++i)
     85             if(p[i].op == 2) ans[p[i].id] = a;
     86         return ;
     87     }
     88     initTree();
     89     int mid = a + ((b - a) >> 1), t = l - 1;
     90     for(int i = l; i <= r; ++i) {
     91         if(p[i].op == 1) {
     92             if(p[i].c > mid) modify(1, 1, n, p[i].a, p[i].b), p[i].v = 1;
     93             else p[i].v = 0;
     94         } else {
     95             int s = query(1, 1, n, p[i].a, p[i].b);
     96             if(p[i].c <= s) p[i].v = 1;
     97             else p[i].v = 0, p[i].c -= s;
     98         }
     99         t += !p[i].v;
    100     }
    101     sort(p + l, p + r + 1);
    102     work(a, mid, l, t);
    103     work(mid + 1, b, t + 1, r);
    104 }
    105 
    106 int main() {
    107     scanf("%d%d", &n, &m);
    108     for(int i = 1; i <= m; ++i) p[i].read(i);
    109     memset(ans + 1, 0x80, m * sizeof(int));
    110     work(-n, n, 1, m);
    111     for(int i = 1; i <= m; ++i)
    112         if(ans[i] >= -n) printf("%d
    ", ans[i]);
    113 }
    View Code
  • 相关阅读:
    关于C++中如何判断文件,目录存在的若干方法
    AStyle2.02在VS2008下的使用
    opencv与wxwidgets冲突(第三方库jpeg,tiff,png,zlib所引起)
    C和C++获取文件大小的方法总结
    跨平台项目组织2
    md5函数C语言实现
    分享本人自编的一个跨平台项目:伙食管理小软件
    win7 vs2008 release mt.exe停止工作
    跨平台项目组织
    SQL注入语句 (很全)
  • 原文地址:https://www.cnblogs.com/oyking/p/3905850.html
Copyright © 2011-2022 走看看