洛谷 P3332 [ZJOI2013]K大数查询 || bzoj3110

用树套树就很麻烦,用整体二分就成了裸题。。。。

错误:

1.尝试线段树套平衡树,码农,而且n*log^3(n)慢慢卡反正我觉得卡不过去

2.线段树pushdown写错。。。加法tag对于区间和的更新应该要乘上区间长度的

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 using namespace std;
  5 typedef long long LL;
  6 struct Q
  7 {
  8     LL type,a,b,c,num;
  9 }q[50100],qt1[50100],qt2[50100];
 10 LL ans[50100],qnum;
 11 LL n,m;
 12 namespace SegT
 13 {
 14 #define mid (l+((r-l)>>1))
 15 #define lc (num<<1)
 16 #define rc (num<<1|1)
 17 LL dat[200100],addv[200100];
 18 LL L,R,x;
 19 void pd(LL l,LL r,LL num)
 20 {
 21     if(addv[num])
 22     {
 23         dat[lc]+=(mid-l+1)*addv[num];addv[lc]+=addv[num];
 24         dat[rc]+=(r-mid)*addv[num];addv[rc]+=addv[num];
 25         addv[num]=0;
 26     }
 27 }
 28 void _addx(LL l,LL r,LL num)
 29 {
 30     if(L<=l&&r<=R)    {dat[num]+=(r-l+1)*x;addv[num]+=x;return;}
 31     pd(l,r,num);
 32     if(L<=mid)    _addx(l,mid,lc);
 33     if(mid<R)    _addx(mid+1,r,rc);
 34     dat[num]=dat[lc]+dat[rc];
 35 }
 36 LL _query(LL l,LL r,LL num)
 37 {
 38     if(L<=l&&r<=R)    return dat[num];
 39     pd(l,r,num);LL ans=0;
 40     if(L<=mid)    ans+=_query(l,mid,lc);
 41     if(mid<R)    ans+=_query(mid+1,r,rc);
 42     return ans;
 43 }
 44 void addx(LL l,LL r,LL d)
 45 {
 46     L=l;R=r;x=d;_addx(1,n,1);
 47 }
 48 LL query(LL l,LL r)
 49 {
 50     L=l;R=r;return _query(1,n,1);
 51 }
 52 #undef mid
 53 #undef lc
 54 #undef rc
 55 }
 56 void solve(LL lp,LL rp,LL l,LL r)
 57 {
 58     if(lp>rp)    return;
 59     LL i;
 60     if(l==r)
 61     {
 62         for(i=lp;i<=rp;i++)
 63             if(q[i].type==2)
 64                 ans[q[i].num]=l;
 65         return;
 66     }
 67     LL mid=l+((r-l)>>1),tlen1=0,tlen2=0,t;
 68     for(i=lp;i<=rp;i++)
 69     {
 70         if(q[i].type==1)
 71         {
 72             if(q[i].c>mid)
 73             {
 74                 SegT::addx(q[i].a,q[i].b,1);
 75                 qt1[++tlen1]=q[i];
 76             }
 77             else
 78                 qt2[++tlen2]=q[i];
 79         }
 80         else
 81         {
 82             t=SegT::query(q[i].a,q[i].b);
 83             if(t>=q[i].c)
 84                 qt1[++tlen1]=q[i];
 85             else
 86                 qt2[++tlen2]=q[i],qt2[tlen2].c-=t;
 87         }
 88     }
 89     for(i=lp;i<=rp;i++)
 90         if(q[i].type==1&&q[i].c>mid)
 91             SegT::addx(q[i].a,q[i].b,-1);
 92     memcpy(q+lp,qt1+1,sizeof(Q)*tlen1);
 93     memcpy(q+lp+tlen1,qt2+1,sizeof(Q)*tlen2);
 94     solve(lp,lp+tlen1-1,mid+1,r);
 95     solve(lp+tlen1,rp,l,mid);
 96 }
 97 int main()
 98 {
 99     LL i;
100     scanf("%lld%lld",&n,&m);
101     for(i=1;i<=m;i++)
102     {
103         scanf("%lld%lld%lld%lld",&q[i].type,&q[i].a,&q[i].b,&q[i].c);
104         if(q[i].type==2)    q[i].num=++qnum;
105     }
106     solve(1,m,-50000,50000);
107     for(i=1;i<=qnum;i++)    printf("%lld\n",ans[i]);
108     return 0;
109 }


洛谷 P3332 [ZJOI2013]K大数查询 || bzoj3110

原文地址:https://www.cnblogs.com/hehe54321/p/8970707.html

时间: 2024-11-08 04:21:22

洛谷 P3332 [ZJOI2013]K大数查询 || bzoj3110的相关文章

P3332 [ZJOI2013]K大数查询 整体二分

终于入门整体二分了,勉勉强强算是搞懂了一个题目吧. 整体二分很多时候可以比较好的离线处理区间\(K\)大值的相关问题.考虑算法流程: 操作队列\(arr\),其中有询问和修改两类操作. 每次在答案的可行值域上二分一个\(mid\),把询问的答案\(>mid\)的分在\(R\)部,\(<=mid\)的分在\(L\)部.把修改的值\(>mid\)的分在\(R\)部,\(<=mid\)的分在\(L\)部. 何谓整体二分?就是直接一起二分所有的询问操作的答案,然后暴力扫描当前操作区间,将其

P3332 [ZJOI2013]K大数查询

\(\color{#0066ff}{ 题目描述 }\) 有N个位置,M个操作.操作有两种,每次操作如果是: 1 a b c:表示在第a个位置到第b个位置,每个位置加上一个数c 2 a b c:表示询问从第a个位置到第b个位置,第C大的数是多少. \(\color{#0066ff}{输入格式}\) 第一行N,M接下来M行,每行形如1 a b c或2 a b c \(\color{#0066ff}{输出格式}\) 输出每个询问的结果 \(\color{#0066ff}{输入样例}\) 2 5 1 1

【BZOJ3110】[Zjoi2013]K大数查询 树套树

[BZOJ3110][Zjoi2013]K大数查询 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

BZOJ 3110: [Zjoi2013]K大数查询( 树状数组套主席树 )

BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N)) ----------------------------------------------------------------------------------------- #include<cstdio> #include<cctype> #include<cstring> #include<algorithm> using namespace std;

BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[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

3110: [Zjoi2013]K大数查询 树状数组套线段树

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Status] 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

树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解

[原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 978  Solved: 476 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 Outpu

[ZJOI2013]K大数查询——整体二分

新科技:整体二分 它能解决的典型问题:带修改区间第\(k\)大 大概的做法是这样的:我们一次二分一个值\(mid\),然后依据操作的答案与\(mid\)的大小关系把操作分别划到两边,然后递归下去.也就是相当于二分的是所有询问的答案 感觉其实这个跟在权值线段树上二分一个效果,只是用离线的方式替代掉了那一层权值线段树而已 计算可得复杂度为\(O(nlog^2n)\)(由主定理,\(T(n)=2T(n/2)+O(nlogn)=O(nlog^2n)\)) 拿线段树或者树状数组维护都行 板子题是这一道K大

BZOJ3110 [ZJOI2013] K大数查询(加强数据)

原来的题解:http://www.cnblogs.com/jimzeng/p/bzoj3110.html 有必要特意再写一篇题解…… OrzKPM!KPM加了两组数据结果我原来的代码就被叉了…… 看到数据没有负数KPM就加了负数,然后还卡了long long(极端情况:50000次,每次在1,50000中加入一个同样的数) 需要离散化数据,加long long 然后速度就明显慢了……(9556ms -> 12292ms) 贴代码: 1 #include <iostream> 2 #inc