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]);
}

原文地址:https://www.cnblogs.com/VIrtu0s0/p/10631423.html

时间: 2024-11-06 22:05:45

Codeforces Round #548 (Div. 2) F splay(新坑) + 思维的相关文章

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/contest/988/problem/E Description Polycarp lives on a coordinate line at the point x=0. He goes to his friend that lives at the point x=a. Polycarp can

Codeforces Round #501 (Div. 3) F. Bracket Substring

题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60949 ....看不懂 设dp[i][j][l]表示前i位,左括号-右括号=j,匹配到l了 状态转移,枚举下一个要填的括号,用next数组求状态的l,分别转移 代码 #include<bits/stdc++.h> using namespace std; const int maxn = 207;

Codeforces Round #549 (Div. 2) F 数形结合 + 凸包(新坑)

https://codeforces.com/contest/1143/problem/F 题意 有n条形如\(y=x^2+bx+c\)的抛物线,问有多少条抛物线上方没有其他抛物线的交点 题解 \(y=x^2+bx+c=>y+x^2=bx+c\),转换为点\((x,y+x^2)\)在bx+c的直线上 两个点确定一条抛物线,同时也确定了一条直线 需要选择最上面那些点相邻确定的抛物线,所以维护一个上凸包即可 维护上凸包,当前点在前进方向左边需要向后退,cross(a,b)>=0 代码 #inclu

Codeforces Round #392 (Div. 2) F. Geometrical Progression

原题地址:http://codeforces.com/contest/758/problem/F F. Geometrical Progression time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output For given n, l and r find the number of distinct geometrical pro

Codeforces Round #531 (Div. 3) F. Elongated Matrix(状压DP)

F. Elongated Matrix 题目链接:https://codeforces.com/contest/1102/problem/F 题意: 给出一个n*m的矩阵,现在可以随意交换任意的两行,最后从上到下,从左到右形成一个序列s1,s2.....snm,满足对于任意相邻的两个数,它们差的绝对值的最大值为k. 现在问怎么交换行与行,可以使得最后的这个k最大. 题解: 人生中第一道状压dp~其实还是参考了这篇博客:https://blog.csdn.net/CSDNjiangshan/art

Codeforces Round #530 (Div. 2)F Cookies (树形dp+线段树)

题:https://codeforces.com/contest/1099/problem/F 题意:给定一个树,每个节点有俩个信息x和t,分别表示这个节点上的饼干个数和先手吃掉这个节点上一个饼干的的时间.然后有先手和后手俩个人. ?先手可以这么操作:在规定总时间T到达某个节点然后一定要返回根节点1,期间可以选择吃掉某些节点上的某些饼干(前提是保证剩下的时间能够回到根节点): ?后手可以这么操作:在先手到达的位置和这个位置的孩子之间的连边选择一条让先手吃得更多的边摧毁掉,也可以跳过这个过程: 问

Codeforces Round #615 (Div. 3) F. Three Paths on a Tree

F. Three Paths on a Tree 原题链接:https://codeforces.com/contest/1294/problem/F 题目大意: 给定一棵树,选出三点,使三点连成的j简单路径最大.简而言之,三个点连成的边的集合大小. 解题思路: 假设任取一点为三点连线的公共点,最长路径就是这个点到其他三个点的三条最长边之和,可知这个点一定在直径上(画图分析假设不在时的最长路径可反证).所以先求出树的直径,在使用$ans =(a b+a c+b c) / 2$遍历可以得到第三个点

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)

https://codeforces.com/contest/1328/problem/F 首先把a数组处理成pair对(num,cnt),表示数字num有cnt个,然后按num升序排序离散化一下. 对于一个数x,若想使得小于x的数字都变成x,必须先把所有小于x的数变成x-1,然后再+1变成x. 同理,要使得大于x的数变成x,必须把所有大于x的数字变成x+1,然后再-1变成x. 以上是题意所要求的必须操作. 思路: 1. 用f[i]数组记录离散化后前i大的数字的总数,那么对于任意第i大数字,可以

Codeforces Round #271 (Div. 2) F.Ant colony(线段树 + 统计区间内某数的个数)

F. Ant colony Mole is hungry again. He found one ant colony, consisting of n ants, ordered in a row. Each ant i (1 ≤ i ≤ n) has a strength si. In order to make his dinner more interesting, Mole organizes a version of «Hunger Games» for the ants. He c