【JZOJ 5296】【清华集训2017模拟】Sequence

这里写图片描述

Solution

发现,那个条件2其实没有用,可以用主席树预处理一下,转为数值在x,y之间,
那么这题就变成了求二维平面上的第k大,
这个用整体二分即可,

复杂度: O(nlog(n)2)

Code

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
#define NX(q) ((q)&(-(q)))
#define Gsum(l,r) (find(r)-find((l)-1))
using namespace std;
const int N=100500;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
struct qqww
{
    int x,y,v;
}a[N],p1[N];
struct qwqw
{
    int x,y,v,i,k,p;
}b[N*2],pb[N*2];
int root[N],b10;
struct qwqwq
{
    int l,r,v;
}b1[N*70];
int f[N];
int c[N],Ans[N];
bool PX(qwqw q,qwqw w){return q.p<w.p;}
void build(int l,int r,int e1,int &e,int l1)
{
    if(!e||e1==e)b1[e=++b10]=b1[e1];
    if(l==r){b1[e].v++;return;}
    b1[e].v++;
    int t=(l+r)>>1;
    if(l1<=t)build(l,t,b1[e1].l,b1[e].l,l1);
    else build(t+1,r,b1[e1].r,b1[e].r,l1);
}
int findr(int l,int r,int e1,int e,int l1)
{
    if(l==r)return l;
    int t=(l+r)>>1;
    if(!b1[e].r||b1[b1[e].l].v-b1[b1[e1].l].v>=l1)return findr(l,t,b1[e1].l,b1[e].l,l1);
    return findr(t+1,r,b1[e1].r,b1[e].r,l1-b1[b1[e].l].v+b1[b1[e1].l].v);
}
void add(int q,int e){for(int i=q;i<=n;i+=NX(i))f[i]+=e;}
int find(int q)
{
    int ans=0;
    for(int i=q;i;i-=NX(i))ans+=f[i];
    return ans;
}
void divide(int l,int r,int L,int R,int L1,int R1)
{
    if(l==r)
    {
        fo(i,L1,R1)Ans[b[i].i]=l;
        return;
    }
    if(L1>R1||L>R)return;
    int t=(l+r)>>1;
    int T=0;
    fo(i,L,R)
    {
        a[i-T]=a[i];
        if(a[i].v>t)p1[++T]=a[i];
    }
    T=R-T;
    fo(i,T+1,R)a[i]=p1[i-T];
    int q=L1;
    fo(i,L,T)
    {
        for(;b[q].p<a[i].x&&q<=R1;q++)
        {
            c[b[q].i]+=b[q].k*Gsum(b[q].x,b[q].y);
        }
        add(a[i].y,1);
    }
    for(;q<=R1;q++)c[b[q].i]+=b[q].k*Gsum(b[q].x,b[q].y);
    q=0;
    fo(i,L1,R1)
    {
        b[i-q]=b[i];
        if(c[b[i].i]<b[i].v)
        {
            b[i].v-=c[b[i].i];
            q++;
            pb[q]=b[i];
        }
        if(b[i].k>0)c[b[i].i]=0;
    }
    fo(i,R1-q+1,R1)b[i]=pb[i-R1+q];
    fo(i,L,T)add(a[i].y,-1);
    divide(l,t,L,T,L1,R1-q);
    divide(t+1,r,T+1,R,R1-q+1,R1);
}
int main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    int q,w,e,_,l,r,x,y;
    read(n);
    fo(i,1,n)read(a[i].y),a[i].x=i;
    fo(i,1,n)
    {
        read(a[i].v);
        build(1,n,root[i-1],root[i],a[i].y);
    }
    read(m);
    fo(i,1,m)
    {
        read(b[i*2-1].p),read(b[i*2].p);
        b[i*2-1].p--;
        read(q),read(w);
        b[i*2].x=b[i*2-1].x=findr(1,n,root[b[i*2-1].p],root[b[i*2].p],q);
        b[i*2].y=b[i*2-1].y=findr(1,n,root[b[i*2-1].p],root[b[i*2].p],w);
        b[i*2].v=read(b[i*2-1].v);
        b[i*2-1].k=-1;b[i*2].k=1;
        b[i*2-1].i=b[2*i].i=i;
    }
    sort(b+1,b+1+2*m,PX);
    divide(1,n,1,n,1,m*2);
    fo(i,1,m)printf("%d\n",Ans[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值