1. 程式人生 > 遊戲攻略 >《羊了個羊》12月5日3D圖形分析

《羊了個羊》12月5日3D圖形分析

\(\mathcal Link\)

可以發現,所選物品的優先順序是固定的,因此考慮先對物品排序。

發現難以優化對單個人的處理,由於詢問不相互影響,因此考慮離線處理所有詢問。

每加入一件物品,所有剩餘錢數 \(\geq c_i\) 的人都會購買。

因此我們的操作是:對權值在 \(\left[c_i,+\infty\right)\) 的節點權值減 \(c_i\),答案加 \(1\)

考慮使用平衡樹維護。注意到平衡樹的結構可能被破壞,考慮對於所有在 \([c_i,2c_i-1]\) 之間的節點暴力插入原樹,以維護 BST 的結構。

分析複雜度:每個節點暴力插入一次,權值至少減半,故複雜度 \(\mathcal O(n\log V\log n)\)

#include <cstdio>
#include <cctype>
#include <random>
#include <algorithm>
using namespace std;
char buf[1<<14],*p1=buf,*p2=buf;
#define GetC() ((p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++)
struct Ios{}io;
template <typename _tp>
Ios &operator >>(Ios &in,_tp &x){
	x=0;int w=0;char c=GetC();
	for(;!isdigit(c);w|=c=='-',c=GetC());
	for(;isdigit(c);x=x*10+(c^'0'),c=GetC());
	if(w) x=-x;
	return in;
}
const int N=2e5+5;
mt19937 rnd(19260817);
struct qwq{int c,q;}a[N];
bool operator <(qwq x,qwq y){
	if(x.q!=y.q) return x.q>y.q;
	return x.c<y.c;
}
int sz[N],ch[N][2],key[N];
int val[N],id[N],ans[N],tag1[N],tag2[N];
int rt;
int cnt;
int new_node(int v,int id_){
	int p=++cnt;
	key[p]=rnd();
	val[p]=v;
	id[p]=id_;
	ans[p]=0;
	return p;
}
void maintain(int x){
	sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
}
void push_down(int x){
	int &l=ch[x][0],&r=ch[x][1];
	if(tag1[x]){
		val[l]-=tag1[x];
		val[r]-=tag1[x];
		tag1[l]+=tag1[x];
		tag1[r]+=tag1[x];
	}
	if(tag2[x]){
		ans[l]+=tag2[x];
		ans[r]+=tag2[x];
		tag2[l]+=tag2[x];
		tag2[r]+=tag2[x];
	}
	tag1[x]=tag2[x]=0;
}
int merge(int x,int y){
	if(!x||!y) return x^y;
	if(key[x]>key[y]){
		push_down(x);
		ch[x][1]=merge(ch[x][1],y);
		maintain(x);
		return x;
	}
	else{
		push_down(y);
		ch[y][0]=merge(x,ch[y][0]);
		maintain(y);
		return y;
	}
}
void split(int p,int v,int &x,int &y){
	if(!p){x=y=0;return ;}
	push_down(p);
	if(val[p]<=v)
		x=p,split(ch[p][1],v,ch[x][1],y);
	else 
		y=p,split(ch[p][0],v,x,ch[y][0]);
	maintain(p);
}
void split_rk(int p,int k,int &x,int &y){
	if(!p){x=y=0;return ;}
	push_down(p);
	if(sz[ch[p][0]]+1<=k) x=p,split_rk(ch[p][1],k-sz[ch[p][0]]-1,ch[x][1],y);
	else y=p,split_rk(ch[p][0],k,x,ch[y][0]);
	maintain(p);
}
void ins(int v,int id_){
	int x,y;split(rt,v,x,y);
	rt=merge(merge(x,new_node(v,id_)),y);
}
int res[N];
void dfs(int p){
	if(!p) return ;
	push_down(p);
	dfs(ch[p][0]);
	dfs(ch[p][1]);
	maintain(p);
	res[id[p]]=ans[p];
}
int main(){
	int n,m;io>>n;
	for(int i=1;i<=n;++i) io>>a[i].c>>a[i].q;
	sort(a+1,a+n+1);
	io>>m;
	for(int i=1;i<=m;++i){
		int x;io>>x;ins(x,i);
	}
	for(int i=1;i<=n;++i){
		int x,y,z;split(rt,a[i].c-1,x,y);
		if(y) tag1[y]+=a[i].c,++tag2[y],val[y]-=a[i].c,++ans[y];
		split(y,a[i].c-1,y,z);
		while(y){
			int tmp;split_rk(y,1,tmp,y);
			int p,q;
			split(x,val[tmp],p,q);
			x=merge(merge(p,tmp),q);
		}
		rt=merge(x,z);
	}
	dfs(rt);
	for(int i=1;i<=m;++i) printf("%d ",res[i]);
	return 0;
}