zoukankan      html  css  js  c++  java
  • Bzoj 3110: [Zjoi2013]K大数查询 树套树

    3110: [Zjoi2013]K大数查询

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 3738  Solved: 1484
    [Submit][Status][Discuss]

    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

    输出每个询问的结果

    Sample Input

    2 5
    1 1 2 1
    1 1 2 2
    2 1 1 2
    2 1 1 1
    2 1 2 3

    Sample Output

    1
    2
    1

    HINT



    【样例说明】

    第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1

    的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是

    1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3

    大的数是 1 。‍


    N,M<=50000,N,M<=50000

    a<=b<=N

    1操作中abs(c)<=N

    2操作中c<=Maxlongint


    Source

     题解:
    权值线段树套区间线段树。
    数据加强了。。。要开long long。。。c有负数了。。。
    离散一下就行了。。。
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define MAXN 50010
      4 #define LL long long
      5 struct node
      6 {
      7     int left,right;
      8     LL tag,sum;
      9 }tree[MAXN*300];
     10 int n,SIZE,s1[MAXN],s2[MAXN],s3[MAXN],s4[MAXN],cc[MAXN],root[MAXN*5];
     11 int read()
     12 {
     13     int s=0,fh=1;char ch=getchar();
     14     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     15     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     16     return s*fh;
     17 }
     18 void Pushup(int k)
     19 {
     20     int l=tree[k].left,r=tree[k].right;
     21     tree[k].sum=tree[l].sum+tree[r].sum;
     22 }
     23 void Pushdown(int k,int ql,int qr)
     24 {
     25     if(tree[k].left==0)tree[k].left=++SIZE;
     26     if(tree[k].right==0)tree[k].right=++SIZE;
     27     int l=tree[k].left,r=tree[k].right;
     28     if(tree[k].tag!=0)
     29     {
     30         tree[l].tag+=tree[k].tag;
     31         tree[r].tag+=tree[k].tag;
     32         int mid=(ql+qr)/2;
     33         tree[l].sum+=(LL)(mid-ql+1)*tree[k].tag;
     34         tree[r].sum+=(LL)(qr-mid)*tree[k].tag;
     35         tree[k].tag=0;
     36     }
     37 }
     38 void Update2(int &k,int l,int r,int ql,int qr)
     39 {
     40     if(k==0)k=++SIZE;
     41     //if(l==r){tree[k].sum++;return;}
     42     if(ql<=l&&r<=qr){tree[k].tag++;tree[k].sum+=(LL)(qr-ql+1);return;}
     43     Pushdown(k,l,r);
     44     int mid=(l+r)/2;
     45     if(qr<=mid)Update2(tree[k].left,l,mid,ql,qr);
     46     else if(ql>mid)Update2(tree[k].right,mid+1,r,ql,qr);
     47     else {Update2(tree[k].left,l,mid,ql,mid);Update2(tree[k].right,mid+1,r,mid+1,qr);}
     48     Pushup(k);
     49 }
     50 void Update1(int k,int l,int r,int ql,int qr,int K)
     51 {
     52     Update2(root[k],1,n,ql,qr);
     53     if(l==r)return;
     54     int mid=(l+r)/2;
     55     if(K<=mid)Update1(k*2,l,mid,ql,qr,K);
     56     else Update1(k*2+1,mid+1,r,ql,qr,K);
     57     //else{Update1(k*2,l,mid,ql,mid,K);Update1(k*2+1,mid+1,r,mid+1,qr,K);}
     58 }
     59 LL Find2(int k,int l,int r,int ql,int qr)
     60 {
     61     if(k==0)return 0;
     62     if(ql<=l&&r<=qr)return tree[k].sum;
     63     Pushdown(k,l,r);
     64     int mid=(l+r)/2;
     65     if(qr<=mid)return Find2(tree[k].left,l,mid,ql,qr);
     66     else if(ql>mid)return Find2(tree[k].right,mid+1,r,ql,qr);
     67     else return Find2(tree[k].left,l,mid,ql,mid)+Find2(tree[k].right,mid+1,r,mid+1,qr);
     68 }
     69 int Find1(int k,int l,int r,int ql,int qr,int K)
     70 {
     71     LL gs=Find2(root[k*2],1,n,ql,qr);
     72     if(l==r)return l;
     73     int mid=(l+r)/2;
     74     if(K<=gs)return Find1(k*2,l,mid,ql,qr,K);
     75     else return Find1(k*2+1,mid+1,r,ql,qr,K-gs);
     76 }
     77 int main()
     78 {
     79     int m,lc,tot,i,k;
     80     n=read();m=read();
     81     lc=0;
     82     for(i=1;i<=m;i++)
     83     {
     84         s1[i]=read();s2[i]=read();s3[i]=read();s4[i]=read();
     85         if(s1[i]==1)cc[++lc]=s4[i];
     86     }
     87     sort(cc+1,cc+lc+1);
     88     tot=unique(cc+1,cc+lc+1)-(cc+1);
     89     SIZE=0;
     90     for(i=1;i<=m;i++)
     91     {
     92         if(s1[i]==1)
     93         {
     94             k=lower_bound(cc+1,cc+tot+1,s4[i])-cc;
     95             Update1(1,1,tot,s2[i],s3[i],tot-k+1);
     96         }
     97         else
     98         {
     99             k=Find1(1,1,tot,s2[i],s3[i],s4[i]);
    100             k=tot-k+1;
    101             printf("%d
    ",cc[k]);
    102         }
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    [freemarker篇]03.如何处理空值
    [Android篇]Android Studio + Genymotion 一夜无眠 ,超级详细版本[请使用新版2.0]
    [freemarker篇]02.生成HTML的静态页面
    [freemarker篇]01.入门Freemarker示例
    验证码-直接使用
    jquery基础介绍-转
    VBA与宏
    .net打印
    [CCF] 201612-1 中间数
    [LeetCode] 56. Merge Intervals(vector sort)
  • 原文地址:https://www.cnblogs.com/Var123/p/5326824.html
Copyright © 2011-2022 走看看