1. 题目

BZOJ – 3110:传送门= ̄ω ̄=

LUOGU – 3332:传送门= ̄ω ̄=

2. 题解

哈哈哈终于完美 AC 这题惹!

整体二分就是吼哇 QvQ!

有先决科技点:整体二分解决单点修改区间 kth 问题:传送门= ̄ω ̄=

上面那题是单点修改所以用的树状数组。

这里区间修改就用线段树(Segment tree QvQ)嘛~

代码:

#include <bits/stdc++.h>
#define NS (50005)
#define MS (50005)
#define LS(a) (a<<1)
#define RS(a) (a<<1|1)
using namespace std;
typedef long long LL;
template<typename _Tp>inline void IN(_Tp&dig)
{
    char c;bool flag=0;dig=0;
    while(c=getchar(),!isdigit(c))if(c=='-')flag=1;
    while(isdigit(c))dig=dig*10+c-'0',c=getchar();
    if(flag)dig=-dig;
}
struct Query{int l,r,id,type;LL k;}Q[MS],Q1[MS],Q2[MS];
struct N{int l,r,tag;LL d;}e[NS<<2];
int n,m,cnt,qcnt,ans[MS];
void pdown(int a)
{
    if(e[a].tag)
    {
        e[LS(a)].d+=(e[LS(a)].r-e[LS(a)].l+1)*e[a].tag,e[LS(a)].tag+=e[a].tag;
        e[RS(a)].d+=(e[RS(a)].r-e[RS(a)].l+1)*e[a].tag,e[RS(a)].tag+=e[a].tag;
        e[a].tag=0;
    }
}
void pup(int a){e[a].d=e[LS(a)].d+e[RS(a)].d;}
void build(int l,int r,int a)
{
    e[a].l=l,e[a].r=r;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(l,mid,LS(a)),build(mid+1,r,RS(a));
}
void update(int l,int r,LL d,int a)
{
    if(l<=e[a].l&&e[a].r<=r){e[a].d+=(e[a].r-e[a].l+1)*d,e[a].tag+=d;return;}
    pdown(a);
    if(l<=e[LS(a)].r)update(l,r,d,LS(a));
    if(r>=e[RS(a)].l)update(l,r,d,RS(a));
    pup(a);
}
LL query(int l,int r,int a)
{
    if(l<=e[a].l&&e[a].r<=r)return e[a].d;
    pdown(a);
    LL tot=0;
    if(l<=e[LS(a)].r)tot+=query(l,r,LS(a));
    if(r>=e[RS(a)].l)tot+=query(l,r,RS(a));
    return tot;
}
void binary(int QL,int QR,int l,int r)
{
    if(QL>QR)return;
    if(l==r){for(int i=QL;i<=QR;i++)if(Q[i].type)ans[Q[i].id]=l;return;}
    int mid=(l+r)>>1,x1=0,x2=0;
    for(int i=QL;i<=QR;i++)
        if(Q[i].type)
        {
            LL tmp=query(Q[i].l,Q[i].r,1);
            if(Q[i].k<=tmp)Q1[++x1]=Q[i];
            else Q2[++x2]=Q[i],Q2[x2].k-=tmp;
        }
        else
        {
            if(Q[i].k<=mid)update(Q[i].l,Q[i].r,1,1),Q1[++x1]=Q[i];
            else Q2[++x2]=Q[i];
        }
    for(int i=1;i<=x1;i++)if(!Q1[i].type)update(Q1[i].l,Q1[i].r,-1,1);
    for(int i=1;i<=x1;i++)Q[QL+i-1]=Q1[i];
    for(int i=1;i<=x2;i++)Q[QL+x1+i-1]=Q2[i];
    binary(QL,QL+x1-1,l,mid),binary(QL+x1,QR,mid+1,r);
}
int main()
{
    IN(n),IN(m),build(1,n,1);
    int opt,a,b;LL c;
    for(int i=1;i<=m;i++)
        if(IN(opt),IN(a),IN(b),IN(c),opt==1)Q[++cnt]=(Query){a,b,0,0,-c};
        else Q[++cnt]=(Query){a,b,++qcnt,1,c};
    binary(1,cnt,-NS,NS);
    for(int i=1;i<=qcnt;i++)printf("%d\n",-ans[i]);
    return 0;
}
分类: 文章

XZYQvQ

炒鸡辣鸡的制杖蒟蒻一枚QvQ

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注