zoukankan      html  css  js  c++  java
  • 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]);
    }
    
  • 相关阅读:
    Java Math 取整的方式
    Java final 关键词修饰类、方法、变量
    Android Activity 开发常用技巧整理
    Java override 和 overload 的区别
    Android TextView 常用技巧
    Android Adb 常用命令
    Android 实现应用升级方案(暨第三方自动升级服务无法使用后的解决方案)
    Git 常用命令
    Android 常见Crash Log汇总
    Java Annotation 总结
  • 原文地址:https://www.cnblogs.com/VIrtu0s0/p/10631423.html
Copyright © 2011-2022 走看看