題目鏈接:
Codeforces702F
題目大意:有$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]);}
}