[Codeforces702F]T-Shirts——非旋转treap+贪心
题目链接:
题目大意:有$n$种T恤,每种有一个价格$c_{i}$和品质$q_{i}$且每种数量无限。现在有$m$个人,第$i$个人有$v_{i}$元,每人每次会买他能买得起的品质最高的一件T恤(当两件T恤品质相同时优先买价格低的),每人只能买一件每种T恤。求最后每个人买的T恤件数。
暴力的方法是将T恤品质从大到小排序,对于每个人从第一种T恤(排序后的第一种)开始模拟每件T恤,能买就买,不能买就跳过。
发现暴力的方法是对于每个人决策每件T恤,我们可以对于每件T恤来决策哪些人能买,用非旋转$treap$来维护每个人还剩的钱数。
那么每次就是将权值大于$q_{i}$的人的权值都减少$q_{i}$并把答案都增加$1$。
对于区间修改我们直接打标记即可,但问题是无法将被修改的部分和没被修改的部分合并。
因为非旋转$treap$的合并要求一棵树的最大权值小于另一棵树的最小权值,而被修改部分在权值减小之后会有一部分的权值比未被修改部分最大权值小。
那么我们就把这部分暴力插入到未被修改的那棵树中,剩下被修改的那部分直接合并。
假设被暴力插入的权值为$x$,那么$x-q_{i}<q_{i},x>=q_{i}$,也就是说$2q_{i}>x,q_{i}>\frac{x}{2}$,即每次暴力插入的数权值减半,所以每个数最多暴力插入$log_{v_{i}}$次。
总时间复杂度是$O((n+\sum log_{v_{i}})log_{m})$。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int ls[200010];
int rs[200010];
int val[200010];
int num[200010];
int r[200010];
int sum[200010];
int tag[200010];
int res[200010];
int root;
int n,m,x;
int cnt;
int a,b,c,d;
int L,R;
struct lty
{
int c,v;
}q[200010];
queue<int>Q;
inline int build(int v)
{
int rt=++cnt;
r[rt]=rand();
val[rt]=v;
return rt;
}
inline void add(int rt,int x,int y)
{
tag[rt]+=x;
val[rt]+=x;
sum[rt]+=y;
res[rt]+=y;
}
inline void pushdown(int rt)
{
if(tag[rt]&&sum[rt])
{
add(ls[rt],tag[rt],sum[rt]);
add(rs[rt],tag[rt],sum[rt]);
tag[rt]=sum[rt]=0;
}
}
inline int merge(int x,int y)
{
if(!x||!y)
{
return x+y;
}
pushdown(x);
pushdown(y);
if(r[x]<r[y])
{
rs[x]=merge(rs[x],y);
return x;
}
else
{
ls[y]=merge(x,ls[y]);
return y;
}
}
inline void split(int rt,int &x,int &y,int k)
{
if(!rt)
{
x=y=0;
return ;
}
pushdown(rt);
if(val[rt]>=k)
{
y=rt;
split(ls[rt],x,ls[y],k);
}
else
{
x=rt;
split(rs[rt],rs[x],y,k);
}
}
inline bool cmp(lty a,lty b)
{
return a.v==b.v?a.c<b.c:a.v>b.v;
}
inline void dfs(int rt)
{
pushdown(rt);
if(ls[rt])
{
dfs(ls[rt]);
}
if(rs[rt])
{
dfs(rs[rt]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&q[i].c,&q[i].v);
}
sort(q+1,q+1+n,cmp);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&x);
split(root,a,b,x);
root=merge(merge(a,build(x)),b);
}
for(int i=1;i<=n;i++)
{
split(root,a,b,q[i].c);
split(b,b,c,2*q[i].c);
add(b,-q[i].c,1);
add(c,-q[i].c,1);
Q.push(b);
while(!Q.empty())
{
int now=Q.front();
Q.pop();
pushdown(now);
if(ls[now])
{
Q.push(ls[now]);
}
if(rs[now])
{
Q.push(rs[now]);
}
ls[now]=rs[now]=0;
split(a,a,d,val[now]);
a=merge(merge(a,now),d);
}
root=merge(a,c);
}
dfs(root);
for(int i=1;i<=m;i++)
{
printf("%d ",res[i]);
}
}
[Codeforces702F]T-Shirts——非旋转treap+贪心的更多相关文章
- [bzoj3173]最长上升子序列_非旋转Treap
最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为 ...
- 关于非旋转treap的学习
非旋转treap的操作基于split和merge操作,其余操作和普通平衡树一样,复杂度保证方式与旋转treap差不多,都是基于一个随机的参数,这样构出的树树高为\(logn\) split 作用:将原 ...
- BZOJ5063旅游——非旋转treap
题目描述 小奇成功打开了大科学家的电脑. 大科学家打算前往n处景点旅游,他用一个序列来维护它们之间的顺序.初 始时,序列为1,2,...,n. 接着,大科学家进行m次操作来打乱顺序.每次操作有6步: ...
- BZOJ3223文艺平衡树——非旋转treap
此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...
- BZOJ3224普通平衡树——非旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
- [NOIP]2017列队——旋转treap/非旋转treap
Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia所在的方阵中有n × m名学生,方阵的行数为 n,列数为m. 为了便 ...
- BZOJ3729Gty的游戏——阶梯博弈+巴什博弈+非旋转treap(平衡树动态维护dfs序)
题目描述 某一天gty在与他的妹子玩游戏.妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子移动到父节点,询问将某个节点的子树中的石子移动到这个节点先手是否有必胜策略.gt ...
- BZOJ1552[Cerc2007]robotic sort&BZOJ3506[Cqoi2014]排序机械臂——非旋转treap
题目描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. 第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. 输出 输出共一行,N个用空格隔开 ...
- BZOJ1251序列终结者——非旋转treap
题目描述 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技 ...
随机推荐
- 大湾区联动:广州深圳助力东莞.NET俱乐部首次线下活动
新年伊始,经过一个寒冬考验后的.NET社区热情不减,长沙.南京.合肥.东莞先后建立以微信为主要平台的线上.NET社区.并相继开始筹划和组织各地区的首次线下活动.东莞作为粤港澳大湾区的腹地,制造业基地, ...
- 轨迹系列5——验证轨迹GPS坐标转换为本地坐标的四/七参数是否准确的一种方案
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 目前对多个项目轨迹不准确的情况做了排查,发现导致轨迹偏移百分 ...
- 设置Editext的光标宽高与颜色
在Editext的布局属性上加上 android:textCursorDrawable="@drawable/cursor_shape" cursor_shape如下: <? ...
- PJSUA2开发文档--第六章 媒体 Media类
6. 媒体(Media) 媒体对象是能够产生媒体或接受媒体的对象. Media的重要子类是AudioMedia,它代表音频媒体.PJSUA2支持多种类型的音频媒体对象: 捕获设备的AudioMedia ...
- 单台MongoDB实例开启Oplog
背景 随着数据的积累,MongoDB中的数据量越来越大,数据分析团队从数据库中抽取变化数据(假如依据栏位createdatetime,transdatetime),越来越困难.我们知道MongoDB的 ...
- Postman安装与使用
Postman一款非常流行的API调试工具.其实,开发人员用的更多.因为测试人员做接口测试会有更多选择,例如Jmeter.soapUI等.不过,对于开发过程中去调试接口,Postman确实足够的简单方 ...
- 多线程控制工具类--倒计时器CountDownLatch的使用(模仿火箭发射)
package com.thread.test.Lock; import java.util.Random; import java.util.concurrent.CountDownLatch; i ...
- Ambari Metrics 详解
Ambari Metrics 原理 Ambari Metrics System 简称为 AMS,它主要为系统管理员提供了集群性能的监察功能.Metrics 一般分为 Cluster.Host 以及 S ...
- OpenCV 与 OpenGL 的关系是什么?
OpenCV是 Open Source Computer Vision LibraryOpenGL是 Open Graphics LibraryOpenCV主要是提供图像处理和视频处理的基础算法库,还 ...
- try/catch中finally的执行时间
前言 由于总是搞不清楚try/catch中的一个执行顺序,返回结果.所以总结一下 1.finally没有return 时,可以看出finally确实在return之前执行了 public static ...