ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[CF702F] T-Shirts

2021-04-30 22:35:29  阅读:191  来源: 互联网

标签:ch val int t2 t1 Shirts CF702F define


\(\text{Problem}:\)T-Shirts

\(\text{Solution}:\)

在序列操作的问题中,一种常规的思想是使得被操作物品的信息尽可能少。故转化题目为:将物品以 \(q_{i}\) 从大到小为第一关键字,\(c_{i}\) 从小到大为第二关键字排序。枚举物品 \(i\),对于每个人 \(j\),若 \(v_{j}\geq c_{i}\),则 \(v_{j}\) 减去 \(c_{i}\),\(g_{j}\) 加 \(1\);否则不进行操作。最后查询 \(\forall i\in [1,m],g_{i}\)。

考虑用平衡树维护有序的 \(v_{i}\)。将大于等于 \(c_{i}\) 的 \(v_{j}\) 都打上区间减的 \(tag\) 是不可行的,因为会破坏平衡树的结构。现在考虑这样一种做法:

  • \(0\leq v_{j}<c_{i}\),不操作。

  • \(c_{i}\leq v_{i}<2c_{i}\),将其减去 \(c_{i}\) 后暴力插入平衡树中。

  • \(v_{i}\geq 2c_{i}\),打上区间减 \(c_{i}\) 的标记。

答案正确性显然。分析第二种操作的时间复杂度。发现对于每个 \(v_{j}\),至多只会进行 \(\log c_{i}\) 次操作二,故复杂度正确。

总时间复杂度 \(O(n\log^2 n)\)(令 \(c_{i}\) 与 \(n\) 同阶)。

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=200010;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,m;
struct Node { int c,q; }a[N]; int b[N];
inline bool cp(Node x,Node y) { return x.q==y.q?x.c<y.c:x.q>y.q; }
int root,ch[N][2],siz[N],rnd[N],val[N],sum[N],t1[N],t2[N];
inline int New_Node(int x,int k) { val[k]=x, siz[k]=1, rnd[k]=rand(); return k; }
inline void Push_Up(int x) { siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; }
inline void Push_Down(int x)
{
	if(ch[x][0]) t1[ch[x][0]]+=t1[x], t2[ch[x][0]]+=t2[x], val[ch[x][0]]-=t1[x], sum[ch[x][0]]+=t2[x];
	if(ch[x][1]) t1[ch[x][1]]+=t1[x], t2[ch[x][1]]+=t2[x], val[ch[x][1]]-=t1[x], sum[ch[x][1]]+=t2[x];
	t1[x]=t2[x]=0;
}
void Split(int root,int k,int &x,int &y)
{
	if(!root) { x=y=0; return; }
	Push_Down(root);
	if(val[root]<=k) x=root, Split(ch[root][1],k,ch[root][1],y);
	else y=root, Split(ch[root][0],k,x,ch[root][0]);
	Push_Up(root);
}
int Merge(int x,int y)
{
	if(!x||!y) return x|y;
	Push_Down(x), Push_Down(y);
	if(rnd[x]<rnd[y]) { ch[x][1]=Merge(ch[x][1],y), Push_Up(x); return x; }
	else { ch[y][0]=Merge(x,ch[y][0]), Push_Up(y); return y; }
}
inline void Insert(int k,int ui)
{
	int x,y;
	Split(root,k,x,y);
	root=Merge(Merge(x,New_Node(k,ui)),y);
}
void Change(int x,int &to,int C)
{
	Push_Down(x);
	if(ch[x][0]) Change(ch[x][0],to,C);
	if(ch[x][1]) Change(ch[x][1],to,C);
	ch[x][0]=ch[x][1]=0;
	int y,z;
	val[x]-=C, sum[x]++;
	Split(to,val[x],y,z);
	to=Merge(Merge(y,x),z);
}
inline void UpDate(int C)
{
	int x,y,z;
	Split(root,C-1,x,y);
	Split(y,C*2-1,y,z);
	if(z) val[z]-=C, t1[z]+=C, sum[z]++, t2[z]++;
	Change(y,x,C);
	root=Merge(x,z);
}
void Down(int x)
{
	Push_Down(x);
	if(ch[x][0]) Down(ch[x][0]);
	if(ch[x][1]) Down(ch[x][1]);
}
signed main()
{
	srand(time(NULL));
	n=read();
	for(ri int i=1;i<=n;i++) a[i].c=read(), a[i].q=read();
	sort(a+1,a+1+n,cp);
	m=read();
	for(ri int i=1;i<=m;i++) b[i]=read(), Insert(b[i],i);
	for(ri int i=1;i<=n;i++) UpDate(a[i].c);
	Down(root);
	for(ri int i=1;i<=m;i++) printf("%d ",sum[i]);
	puts("");
	return 0;
}

标签:ch,val,int,t2,t1,Shirts,CF702F,define
来源: https://www.cnblogs.com/zkdxl/p/14723451.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有