T-Shirts

T-Shirts

将人按钱数从小到大排序,想到对于每个物品可以对一个区间内的人进行影响,那我们建立平衡树,将人的作为其中的元素插入,将物品按品质价格排序,每次看作是一个操作进行区间修改。

不过不能修改后不做处理,如果打上减标记后权值减少可以会造成权值相交,我们再插回去的话就不满足平衡树的性质了。

考虑将 \([c,2c]\) 的节点暴力插入 \([1,c-1]\),对于 \([2c+1,n]\) 的节点打标记处理,为什么暴力是对的,因为满足 \([c,2c]\) 的节点减 \(c\) 对半,每个点最多操作 \(logc_i\) 次。

#include<bits/stdc++.h>
#define ll long long
#define int ll
#define ls t[p].l
#define rs t[p].r
#define re register
#define pb push_back
#define pir pair<int,int>
#define f(a,x,i) for(int i=a;i<=x;i++)
#define fr(a,x,i) for(int i=a;i>=x;i--)
using namespace std;
const int N=4e5+10;
const int M=3e5+10;
const int mod=1e9+7;
mt19937 rnd(251);
int n,m;
int cnt=0;
int root=0;
struct ss{
int c,q;
}a[N];
int ans[N];
bool cmp(ss g,ss h){
if(g.q!=h.q){
return g.q>h.q;
}
return g.c<h.c;
}
struct Tree{
int rnd;
int l,r;
int val;
int id;
int cnt;
int tag1,tag2;
}t[N];
void pushdown(int p){
if(t[p].tag1){
int c=t[p].tag1;
if(t[p].l) t[ls].tag1+=c,t[ls].val-=c;
if(t[p].r) t[rs].tag1+=c,t[rs].val-=c;
t[p].tag1=0;
}
if(t[p].tag2){
int c=t[p].tag2;
if(t[p].l) t[ls].tag2+=c,t[ls].cnt+=c;
if(t[p].r) t[rs].tag2+=c,t[rs].cnt+=c;
t[p].tag2=0;
}
}
void split(int p,int val,int &x,int &y){
if(!p){
x=y=0;
return;
}
pushdown(p);
if(t[p].val<=val){
x=p;
split(t[p].r,val,t[p].r,y);
}
else{
y=p;
split(t[p].l,val,x,t[p].l);
}
}
int merge(int x,int y){
if(!x||!y){
return x+y;
}
pushdown(x);
pushdown(y);
if(t[x].rnd<t[y].rnd){
t[x].r=merge(t[x].r,y);
return x;
}
else{
t[y].l=merge(x,t[y].l);
return y;
}
}
int add(int val,int id){
int p=++cnt;
t[p].rnd=rnd();
t[p].id=id;
t[p].val=val;
return p;
}
void insert(int val,int id){
int x,y;
split(root,val,x,y);
int z=add(val,id);
root=merge(merge(x,z),y);
}
void dfs(int x,int &y,int z){
if(!x) return;
pushdown(x);
dfs(t[x].l,y,z);
dfs(t[x].r,y,z);
t[x].l=t[x].r=0;
t[x].cnt++;
t[x].val-=z;
int k1,k2;
split(y,t[x].val,k1,k2);
y=merge(merge(k1,x),k2);
}
void dfs2(int p){
if(!p) return;
pushdown(p);
ans[t[p].id]=t[p].cnt;
dfs2(ls);dfs2(rs);
}
signed main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].c>>a[i].q;
}
sort(a+1,a+1+n,cmp);
cin>>m;
for(int i=1;i<=m;i++){
int x;
cin>>x;
insert(x,i);
}
for(int i=1;i<=n;i++){
int x,y,z;
int c=a[i].c;
split(root,c-1,x,y);
split(y,2*c,y,z);
if(z){
t[z].val-=c;
t[z].tag1+=c;
t[z].cnt++;
t[z].tag2++;
}
dfs(y,x,c);
root=merge(x,z);
}
dfs2(root);
for(int i=1;i<=m;i++){
cout<<ans[i]<<" ";
}
return 0;
}

有交合并,未优化不能过。

#include<bits/stdc++.h>
#define ll long long
#define int ll
#define ls t[p].l
#define rs t[p].r
#define re register
#define pb push_back
#define pir pair<int,int>
#define f(a,x,i) for(int i=a;i<=x;i++)
#define fr(a,x,i) for(int i=a;i>=x;i--)
using namespace std;
const int N=2e5+10;
const int M=3e5+10;
const int mod=1e9+7;
mt19937 rnd(251);
int n,m;
int cnt=0;
int root=0;
struct ss{
int c,q;
}a[N];
int ans[N];
bool cmp(ss g,ss h){
if(g.q!=h.q){
return g.q>h.q;
}
return g.c<h.c;
}
struct Tree{
int rnd;
int l,r;
int val;
int id;
int cnt;
int tag1,tag2;
}t[N];
void pushdown(int p){
if(t[p].tag1){
int c=t[p].tag1;
if(t[p].l) t[ls].tag1+=c,t[ls].val-=c;
if(t[p].r) t[rs].tag1+=c,t[rs].val-=c;
t[p].tag1=0;
}
if(t[p].tag2){
int c=t[p].tag2;
if(t[p].l) t[ls].tag2+=c,t[ls].cnt+=c;
if(t[p].r) t[rs].tag2+=c,t[rs].cnt+=c;
t[p].tag2=0;
}
}
void split(int p,int val,int &x,int &y){
if(!p){
x=y=0;
return;
}
pushdown(p);
if(t[p].val<=val){
x=p;
split(t[p].r,val,t[p].r,y);
}
else{
y=p;
split(t[p].l,val,x,t[p].l);
}
}
int merge(int x,int y){
if(!x||!y){
return x|y;
}
if(t[x].rnd<t[y].rnd){
pushdown(x);
t[x].r=merge(t[x].r,y);
return x;
}
else{
pushdown(y);
t[y].l=merge(x,t[y].l);
return y;
}
}
int merge2(int x,int y){
if(!x||!y){
return x|y;
}
int l,r;
if(t[x].rnd<=t[y].rnd){
pushdown(x);
split(y,t[x].val,l,r);
t[x].l=merge2(t[x].l,l);
t[x].r=merge2(t[x].r,r);
return x;
}
else{
pushdown(y);
split(x,t[y].val,l,r);
t[y].l=merge2(t[y].l,l);
t[y].r=merge2(t[y].r,r);
return y;
}
}
int add(int val,int id){
int p=++cnt;
t[p].rnd=rnd();
t[p].id=id;
t[p].val=val;
return p;
}
void insert(int val,int id){
int x,y;
split(root,val,x,y);
int z=add(val,id);
root=merge(merge(x,z),y);
}
void dfs2(int p){
if(!p) return;
pushdown(p);
ans[t[p].id]=t[p].cnt;
dfs2(ls);dfs2(rs);
}
signed main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].c>>a[i].q;
}
sort(a+1,a+1+n,cmp);
cin>>m;
for(int i=1;i<=m;i++){
int x;
cin>>x;
insert(x,i);
}
for(int i=1;i<=n;i++){
int x,y,z;
int c=a[i].c;
split(root,c-1,x,y);
split(y,2*c-1,y,z);
if(y){
t[y].cnt++;
t[y].val-=c;
t[y].tag1+=c;
t[y].tag2++;
}
if(z){
t[z].cnt++;
t[z].val-=c;
t[z].tag1+=c;
t[z].tag2++;
}
root=merge(merge2(x,y),z);
}
dfs2(root);
for(int i=1;i<=m;i++){
cout<<ans[i]<<" ";
}
return 0;
}
posted @   sad_lin  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示