题面传送门

首先肯定将所有物品排个序。

考虑暴力做法,对于每个询问,枚举所有物品,能买就买。不过扫一眼就知道无法直接优化。

不妨换个角度,暴力做法是枚举询问,这次我们枚举物品。从左到右依次枚举所有物品,将所有买得起当前物品的询问答案 \(+1\),钱数减去当前物品的价格。这样就貌似与 DS 能够搭得上边了。

于是题目变为:\(n\) 次操作,每次操作将序列所有值 \(\geq c\) 的数减去 \(c\),问每个数被操作了几次。

可还是不好维护啊,平衡树 split 出 \(\geq c\) 的数后你还是要暴力修改啊。

这时候我们就需要用到一种奇淫技巧,学名“势能分析”(咋感觉像物理内容啊qwq)

我们将原序列 split 成三个部分,\([1,c),[c,2c),[2c,\infty)\),显然,第一部分不会被操作,第三部分被操作后相对位置不会发生变化,因此我们只需暴力修改第二部分。

你可能会直觉地认为这样子优化没啥卵用,其实这样做复杂度反倒是对的。

这样看似不起眼的优化为什么就把不可能变成可能了呢?

注意到,我们暴力修改的数都在 \([c,2c)\) 中,也就是修改完之后,原数至多变为原来的一半。也就是说每个数最多被修改 \(\log c_i\) 次,总复杂度线性对数方,可以通过四秒时限。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
template<typename T> void read(T &x){
char c=getchar();T neg=1;
while(!isdigit(c)){if(c=='-') neg=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=neg;
}
const int MAXN=2e5+5;
int Rand(){return rand()<<15|rand();}
int n,m,ans[MAXN+5];
struct event{int c,q;} a[MAXN+5];
bool cmp(event x,event y){if(x.q!=y.q) return x.q>y.q;return x.c<y.c;}
struct node{
int ch[2],id,val,key,cntlz,minlz,cnt;
} s[MAXN+5];
int ncnt=0,rt=0;
void pushdown(int k){
if(s[k].minlz){
if(s[k].ch[0]) s[s[k].ch[0]].minlz+=s[k].minlz,s[s[k].ch[0]].val-=s[k].minlz;
if(s[k].ch[1]) s[s[k].ch[1]].minlz+=s[k].minlz,s[s[k].ch[1]].val-=s[k].minlz;
s[k].minlz=0;
} if(s[k].cntlz){
if(s[k].ch[0]) s[s[k].ch[0]].cntlz+=s[k].cntlz,s[s[k].ch[0]].cnt+=s[k].cntlz;
if(s[k].ch[1]) s[s[k].ch[1]].cntlz+=s[k].cntlz,s[s[k].ch[1]].cnt+=s[k].cntlz;
s[k].cntlz=0;
}
}
void split(int k,int val,int &a,int &b){
if(!k){a=b=0;return;} pushdown(k);
if(s[k].val<=val) a=k,split(s[k].ch[1],val,s[k].ch[1],b);
else b=k,split(s[k].ch[0],val,a,s[k].ch[0]);
}
int merge(int x,int y){
if(!x||!y) return x|y;pushdown(x);pushdown(y);
if(s[x].key<s[y].key) return s[x].ch[1]=merge(s[x].ch[1],y),x;
else return s[y].ch[0]=merge(x,s[y].ch[0]),y;
}
void dfsins(int x,int &y,int z){//insert all nodes in subtree x into subtree y, val-=z
if(!x) return;pushdown(x);
dfsins(s[x].ch[0],y,z);dfsins(s[x].ch[1],y,z);
s[x].ch[0]=s[x].ch[1]=0;s[x].val-=z;s[x].cnt++;
int k1,k2;split(y,s[x].val,k1,k2);y=merge(merge(k1,x),k2);
}
void insert(int x,int id){
int k1,k2;split(rt,x,k1,k2);
ncnt++;s[ncnt].id=id;s[ncnt].key=Rand();s[ncnt].val=x;
rt=merge(merge(k1,ncnt),k2);
}
void dfscalc(int x){
if(!x) return;pushdown(x);
ans[s[x].id]=s[x].cnt;dfscalc(s[x].ch[0]);dfscalc(s[x].ch[1]);
}
int main(){
srand(19260817);scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].c,&a[i].q);
sort(a+1,a+n+1,cmp);scanf("%d",&m);
for(int i=1;i<=m;i++){int x;scanf("%d",&x);insert(x,i);}
for(int i=1;i<=n;i++){
int k1,k2,k3;split(rt,a[i].c-1,k1,k2);split(k2,a[i].c<<1,k2,k3);
if(k3){s[k3].val-=a[i].c;s[k3].cnt++;s[k3].minlz+=a[i].c;s[k3].cntlz++;}
dfsins(k2,k1,a[i].c);rt=merge(k1,k3);
}
for(int i=1;i<=m;i++) ans[s[i].id]=s[i].cnt;
dfscalc(rt);for(int i=1;i<=m;i++) printf("%d ",ans[i]);
return 0;
}

Codeforces 702F - T-shirts(平衡树+势能分析)的更多相关文章

  1. bzoj3211 花神游历各国 线段树,势能分析

    [bzoj3211]花神游历各国 2014年3月17日2,7230 Description   Input   Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input ...

  2. BZOJ5312 冒险 势能分析、线段树

    传送门 区间位赋值.区间求最大值似乎是不能够像一般的线段树一样直接打标记的,但是直接暴力也太没有面子了. 我们考虑优化一下暴力:如果说线段树的一段区间内在当前修改的所有位置上所有数都是相同的,那么这个 ...

  3. Codeforces 679E - Bear and Bad Powers of 42(线段树+势能分析)

    Codeforces 题目传送门 & 洛谷题目传送门 这个 \(42\) 的条件非常奇怪,不过注意到本题 \(a_i\) 范围的最大值为 \(10^{14}\),而在值域范围内 \(42\) ...

  4. DZY Loves Colors CodeForces - 444C (线段树势能分析)

    大意:有$n$个格子, 初始$i$位置的颜色为$i$, 美丽值为0, 有两种操作 将区间$[l,r]$内的元素全部改为$x$, 每个元素的美丽值增加$|x-y|$, $y$为未改动时的值 询问区间$[ ...

  5. @codeforces - 702F@ T-Shirts

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 有 n 件 T-shirt,第 i 件 T-shirt 有一个 ...

  6. 势能分析(splay分析)

    定义 第\(x\)次操作后,势能为\(\phi(x)\),该操作实际复杂度\(c(x)\),均摊复杂度\(a(x)\). 定义\(a(x)=c(x)+\phi(x)-\phi(x-1)\). 那么总复 ...

  7. Codeforces 420D Cup Trick 平衡树

    Cup Trick 平衡树维护一下位置. #include<bits/stdc++.h> #include <bits/extc++.h> #define LL long lo ...

  8. codeforces:855D Rowena Ravenclaw's Diadem分析和实现

    题目大意: 提供n个对象,分别编号为1,...,n.每个对象都可能是某个编号小于自己的对象的特例或是成分.认为某个对象的特例的特例依旧是该对象的特例,即特例关系传递,同样一个对象的成分的成分依旧是该对 ...

  9. [模板] 平衡树: Splay, 非旋Treap, 替罪羊树

    简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...

随机推荐

  1. 深入理解Java虚拟机之类加载机制篇

    概述 ​ 虚拟机把描述类的数据从 Class 文件加载到内存中,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,就是虚拟机的类加载机制. ​ 在Java语言里面,类型的 ...

  2. BUAA 2020 软件工程 个人博客作业

    BUAA 2020 软件工程 个人博客作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业 ...

  3. HMS Core Keyring携手航班管家和高铁管家,打造美好出行体验

    高铁管家是国内最早⽀持⼿机⽀付购买⽕⻋票App之⼀,日活用户超380万,为⽤户提供一站式铁路出⾏服务.高铁管家母公司--深圳市活⼒天汇科技股份有限公司是国内智能⼤出⾏的开创者,先后推出航班管家.⾼铁管 ...

  4. 如何理解Stand SPI Dual SPI 和Quad SPI??

    1.首先看一下接口 Standard SPI: CLK, /CS, DI, DO, /WP, /Hold Dual SPI: CLK, /CS, IO0, IO1, /WP, /Hold Quad S ...

  5. 设计模式 - Bridge 桥模式

    Bridge桥模式也属于"的单一职责"模式中的典型模式.问题描述:我们绘制图形时,图形可以有不同形状以及不同颜色,比如圆形可以是红的,绿的,方形可以是红的绿的,如果用代码来描绘这些 ...

  6. 【做题记录】 [HEOI2013]SAO

    P4099 [HEOI2013]SAO 类型:树形 \(\text{DP}\) 这里主要补充一下 \(O(n^3)\) 的 \(\text{DP}\) 优化的过程,基础转移方程推导可以参考其他巨佬的博 ...

  7. 『学了就忘』Linux基础 — 9、虚拟机中快照的使用

    目录 1.快照的含义 2.快照的使用 步骤一:创建拍摄快照 步骤二:填写快照信息并创建 步骤三:查看快照 步骤四:操作快照 3.管理虚拟机小技巧 4.关于快照说明 快照和克隆是VMware中两个非常实 ...

  8. 『学了就忘』Linux基础 — 15、了解Linux系统的目录结构

    目录 1.一级目录说明 (1)一级目录列表 (2)/bin/和/sbin/目录说明 (3)/boot/目录说明 (4)/lib/和/lib64/目录说明 (5)/lost+found/目录说明 (6) ...

  9. shell 脚本控制命令的执行顺序

    &&,||,(),{},& 五个符号的运用shell脚本执行命令的时候,有时候会依赖于前一个命令是否执行成功.而&&和||就是用来判断前一个命令执行效果的. 也 ...

  10. Linux初学者:从不同角度理解Linux系统

    在我初学Linux系统时,虽然已经掌握了一些命令,但总觉得还是很混乱.大家新买的笔记本如果是Windows系统,那么第一件事往往就是分区,目的就是将系统和软件分开.然而Linux却没有类似于Windo ...