Codeforces Round #548 (Div. 2) F splay(新坑) + 思维

https://codeforces.com/contest/1139/problem/F

题意

有m个人,n道菜,每道菜有\(p_i\),\(s_i\),\(b_i\),每个人有\(inc_j\),\(pref_j\),一个人可以买一道菜的条件是
1. \(p_i \leq inc_j \leq s_i\)
2. \(|b_i - pref_j| \leq inc_j-p_i\)
,问每个人分别能买多少道菜

题解

  • 转化一下公式
    1. \(p_i \leq inc_j \leq s_i\)
    • 下面两个满足其一即可
    1. \(b_i + p_i \leq inc_j + pref_j\)
    2. \(p_i - b_i \leq inc_j - pref_j\)
  • 对于每个j只需要找出有多少个i满足要求就行
  • \(p_i \leq inc_j \leq s_i\)建立时间节点并排序,然后从前往后扫一遍,用两颗splay维护后两个式子并计数

代码

#include<bits/stdc++.h>
#define ls(x) tr[x].son[0]
#define rs(x) tr[x].son[1]
#define MAXN 200005
using namespace std;
struct SPLAY{
    int root=0,tot=0;
    struct node{
        int son[2],par;
        int sz,tsz,v;
        void init(int _v=0,int _sz=0){
            v=_v;
            tsz=sz=_sz;
            son[0]=son[1]=par=0;
        }
    }tr[MAXN];
    void push_up(int x){
        tr[x].tsz=tr[x].sz+tr[ls(x)].tsz+tr[rs(x)].tsz;
    }
    int chk(int x){
        return rs(tr[x].par)==x;
    }
    void rot(int x){
        int y=tr[x].par,z=tr[y].par,k=chk(x),w=tr[x].son[k^1];
        tr[y].son[k]=w;tr[w].par=y;
        tr[z].son[chk(y)]=x;tr[x].par=z;
        tr[x].son[k^1]=y;tr[y].par=x;
        push_up(y);
        push_up(x);
    }
    void splay(int x,int goal){
        while(tr[x].par!=goal){
            int y=tr[x].par,z=tr[y].par;
            if(z!=goal){
                if(chk(x)==chk(y))rot(y);
                else rot(x);
            }
            rot(x);
        }
        if(!goal)root=x;
    }
    void insert(int v,int sz){
        int p=root,ff=0;
        while(p&&tr[p].v!=v){
            ff=p;
            p=tr[p].son[v>tr[p].v];
        }
        if(p){
            tr[p].sz+=sz;
        }else{
            p=++tot;
            if(ff)tr[ff].son[v>tr[ff].v]=p;
            tr[p].init(v,sz);
            tr[p].par=ff;
        }
        splay(p,0);
    }
    int count(int v){
        insert(v,1);
        int re=tr[rs(root)].tsz;
        insert(v,-1);
        return re;
    }
}V[2];
int n,m,p[MAXN],s[MAXN],b[MAXN],inc[MAXN],pref[MAXN],ans[MAXN];
int cnt=0,tot=0;

struct node{
    int v,id,kd;
}A[MAXN*4];
bool cmp(node x,node y){
    if(x.v==y.v)return x.kd<y.kd;
    return x.v<y.v;
}
void add(int v,int id,int kd){
    A[++tot].v=v;
    A[tot].id=id;
    A[tot].kd=kd;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)scanf("%d",&p[i]),add(p[i],i,1);   
    for(int i=1;i<=n;i++)scanf("%d",&s[i]),add(s[i],i,3);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    for(int i=1;i<=m;i++)scanf("%d",&inc[i]),add(inc[i],i,2);
    for(int i=1;i<=m;i++)scanf("%d",&pref[i]);
    sort(A+1,A+tot+1,cmp);
    for(int i=1;i<=tot;i++){
        int id=A[i].id;
        if(A[i].kd==1){
            cnt++;
            V[0].insert(b[id]+p[id],1);
            V[1].insert(p[id]-b[id],1); 
        }else if(A[i].kd==2){
            ans[id]=cnt-V[0].count(inc[id]+pref[id])-V[1].count(inc[id]-pref[id]);  
        }else{
            cnt--;
            V[0].insert(b[id]+p[id],-1);
            V[1].insert(p[id]-b[id],-1);
        }
    }
    for(int i=1;i<=m;i++)printf("%d ",ans[i]);
}

猜你喜欢

转载自www.cnblogs.com/VIrtu0s0/p/10631423.html