[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 Core应用中使用缓存
NET Core应用中使用缓存 .NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中.对于分布式缓 ...
- <4>Python切片功能剖析
引用文章:https://mp.weixin.qq.com/s/NZ371nKs_WXdYPCPiryocw 切片基础法则: (1)公式,禁止0. (2)i, n同号:从序列的第i位索引起,向右取n- ...
- DVWA 黑客攻防演练(三)命令行注入(Command Injection)
文章会讨论 DVWA 中低.中.高.不可能级别的命令行注入 这里的需求是在服务器上可以 ping 一下其他的服务器 低级 Hacker 试下输入 192.168.31.130; cat /etc/ap ...
- 挖一挖MongoDB的备份与还原(实现指定时间点还原和增量备份还原)
一 研究背景需求 目前作者所在公司的MongoDB数据库是每天凌晨做一次全库完整备份,但数据库出现故障时,只能保证恢复到全备时间点,比如,00:30 做的完整备份,而出现故障是下午18:00,那么现 ...
- TinScrapy-简化的Scrapy原码-查看爬虫的执行流程
学习了自定义的TinyScrapy框架,整理出以下定注释的代码 from twisted.web.client import getPage,defer from twisted.internet i ...
- C++调用Opencv实践中遇到的问题备忘录
1.编写一个显示图片的项目,但显示的图片全灰色. 原因:需要在imshow()函数前加一个namedWindow()函数.https://blog.csdn.net/mao_hui_fei/artic ...
- 【Python 07】汇率兑换1.0-2(基本元素)
1.Python基本元素 (1)缩进:表示代码层次关系(Python中表示程序框架唯一手段) 1个tab或者4个空格 (2)注释:开发者加入的说明信息,不被执行.一个代码块一个注释. # 单行注释(一 ...
- python 中内存释放与函数传递numpy数组问题
numpy.array 作为参数传入函数中时,是作为引用进去的,函数内部对这个数组的修改会直接修改原始数据.在函数中需要暂时修改数据,不对原始数据造成影响的话,需要用 np.copy() 先拷贝一份, ...
- redis 初步认识三(设置登录密码)
1.cmd 2.cd C:\Program Files\Redis 3.redis-cli.exe -h 127.0.0.1 -a 123456
- 【Topcoder 10689】TheSoccerDivOne
题意:给\(n\)个队伍的积分,它们要踢足球,每个队伍剩下4场没有踢. 问踢完后\(0\)队伍最高排名. 思路:首先想了贪心,可惜不对. 那么老实dp. 首先:每个队伍具体和哪个人踢了没有关系. 那么 ...