• P3332 [ZJOI2013]K大数查询


    https://www.luogu.org/problemnew/show/P3332

    题目描述

    有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

    输出格式:

    输出每个询问的结果

    输入输出样例

    输入样例
    2 5
    1 1 2 1
    1 1 2 2
    2 1 1 2
    2 1 1 1
    2 1 2 3
    输出样例
    1
    2
    1

    说明

    样例说明

    第一个操作后位置 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<=long long

      

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,m,tot;
     4 int ans[100050];
     5 struct node
     6 {
     7     int opt,l,r,pos;
     8     long long val;
     9 }num[100050],tl[100050],tr[100050];
    10 long long c1[50050],c2[50050];
    11 void add(int u,int v)
    12 {
    13     for(int i=u;i<=n;i+=i&-i)
    14         c1[i]+=v,c2[i]+=v*u;
    15 }
    16 long long ask(int u)
    17 {
    18     long long tmp=0;
    19     for(int i=u;i;i-=i&-i)
    20         tmp+=(u+1)*c1[i]-c2[i];
    21     return tmp;
    22 }
    23 void calc_add(int l,int r,int v)
    24 {
    25     add(l,v);    add(r+1,-v);
    26 }
    27 long long calc_ask(int l,int r)
    28 {
    29     return ask(r)-ask(l-1);
    30 }
    31 void calc(int L,int R,int l,int r)
    32 {
    33     if(l==r)
    34     {
    35         for(int i=L;i<=R;++i)    ans[num[i].pos]=l;
    36         return ;
    37     }
    38     int mid=(l+r)>>1;
    39     bool fl=0,fr=0;
    40     int topl=0,topr=0;
    41     for(int i=L;i<=R;++i)
    42         if(num[i].opt==1)
    43         {
    44             if(num[i].val<=mid)
    45                 tl[++topl]=num[i];
    46             else
    47             {
    48                 calc_add(num[i].l,num[i].r,1);
    49                 tr[++topr]=num[i];
    50             }
    51         }
    52         else
    53         {
    54             long long tmp=calc_ask(num[i].l,num[i].r);
    55             if(num[i].val>tmp)
    56             {
    57                 num[i].val-=tmp;
    58                 fl=true;
    59                 tl[++topl]=num[i];
    60             }
    61             else
    62             {
    63                 fr=true;
    64                 tr[++topr]=num[i];
    65             }
    66         }
    67     for(int i=L;i<=R;++i)
    68         if(num[i].opt==1&&num[i].val>mid)
    69             calc_add(num[i].l,num[i].r,-1);
    70     for(int i=1;i<=topl;++i)    num[L+i-1]=tl[i];
    71     for(int i=1;i<=topr;++i)    num[L+topl+i-1]=tr[i];
    72     if(fl)    calc(L,L+topl-1,l,mid);
    73     if(fr)    calc(L+topl,R,mid+1,r);
    74 }
    75 int main()
    76 {
    77     scanf("%d%d",&n,&m);
    78     for(int i=1;i<=m;++i)
    79     {
    80         scanf("%d%d%d%lld",&num[i].opt,&num[i].l,&num[i].r,&num[i].val);
    81         if(num[i].opt==2)    num[i].pos=++tot;
    82     }
    83     calc(1,m,-n,n);
    84     for(int i=1;i<=tot;++i)    printf("%d
    ",ans[i]);
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    理解OAuth 2.0
    Npoi导出word(Peanuts)
    轻松搞定javascript日期格式化问题
    史上最全的MSSQL复习笔记
    SQL经典短小代码收集
    Web系统与自控系统数据通讯架构 之 OPC DA DataChangeEventHandler 非热点数据更新策略 ,
    记一次SQL Server insert触发器操作
    记一次单机Nginx调优,效果立竿见影
    windows 显示引用账户已被锁定,且可能无法登录
    C# 使用modbus 读取PLC 寄存器地址
  • 原文地址:https://www.cnblogs.com/wyher/p/10362468.html
Copyright © 2020-2023  润新知