题解:CF2200F Mooclear Reactor 2
闲话
本题解请谨慎观看。
正文
思路
发现每个粒子都有两个属性,然后我赛时直接想到了主席树(没错)。
发现对于答案产生限制的是
如果你知道把一些有着二维属性的问题看作是二维数点问题,将限制看作是
根据上述的描述,我们进而可以想到,假设一个数组
那么对于答案,我们就发现,如果不取这个点,答案就是
对于上述过程,很容易发现,只要先建出一棵主席树,用来维护区间前
总复杂度
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define V vector
#define FOR(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define pb push_back
const int INF=1e9+10,N=2e5+10;
struct node{
int ls,rs,time;
ll w;
}a[N*35];
int root[N],tot=0;
#define mid ((l+r)>>1)
void push_up(int x){
a[x].w=a[a[x].ls].w+a[a[x].rs].w;
a[x].time=a[a[x].ls].time+a[a[x].rs].time;
}
void update(int &x,int last,int l,int r,int pos){
x=++tot;
a[x]=a[last];
if(l==r){
a[x].w+=l;
a[x].time++;
return;
}
if(pos<=mid) update(a[x].ls,a[last].ls,l,mid,pos);
else update(a[x].rs,a[last].rs,mid+1,r,pos);
push_up(x);
}
ll query_sum(int L,int R,int l,int r,int k){//前K大的数的和
if(k==0)return 0ll;
if(a[R].time-a[L].time==0) return 0ll;
if(a[R].time-a[L].time<=k) return a[R].w-a[L].w;
if(l==r){
return min(k,a[R].time-a[L].time)*1ll*l;
}
int tot=a[a[R].rs].time-a[a[L].rs].time;
ll sum=a[a[R].rs].w-a[a[L].rs].w;
if(tot>=k) return query_sum(a[L].rs,a[R].rs,mid+1,r,k);
else return query_sum(a[L].ls,a[R].ls,l,mid,k-tot)+sum;
}
#undef mid
ll ans2[N],premax[N],maxn=-1;//用i个粒子产生的最大值
struct LLS{
int x,y;
friend bool operator <(const LLS &l1,const LLS &l2){
if(l1.y!=l2.y)return l1.y<l2.y;
return l1.x<l2.x;
}
}val[N],num[N];
//有的,商店的
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--){
tot=0;maxn=-1ll;
int n,m;cin>>n>>m;
FOR(i,1,n)cin>>val[i].x>>val[i].y;
sort(val+1,val+1+n);
FOR(i,1,m)cin>>num[i].x>>num[i].y;
FOR(i,1,n){
update(root[i],root[i-1],0,INF,val[i].x);
}
FOR(i,0,n){
LLS fin={0,i};
int it=lower_bound(val+1,val+1+n,fin)-val;
ans2[i]=query_sum(root[it-1],root[n],0,INF,i);
if(i!=0)premax[i]=max(premax[i-1],ans2[i]);
else premax[i]=ans2[i];
maxn=max(maxn,query_sum(root[it-1],root[n],0,INF,min(i+1,n)));
}
FOR(i,1,m){
cout<<max(maxn,premax[num[i].y]+num[i].x)<<" ";
}
cout<<"\n";
}
return 0;
}