P8065 题解
显然离线处理,将询问和球员分别按照年龄排序,然后依次处理询问的时候先每次添加当前可行的球员的
主要问题在于如何去快速维护球员的
考虑使用线段树,预处理出每个球员
于是就可以写出 push_up 操作:
inline Node push_up(int u,int v){
Node ret;
ret.ch[0]=tree[u].ch[tree[v].ch[0]];
ret.ch[1]=tree[u].ch[tree[v].ch[1]];
ret.cnt[0]=tree[v].cnt[0]+tree[u].cnt[tree[v].ch[0]];
ret.cnt[1]=tree[v].cnt[1]+tree[u].cnt[tree[v].ch[1]];
ret.val[0]=tree[v].val[0]+tree[u].val[tree[v].ch[0]];
ret.val[1]=tree[v].val[1]+tree[u].val[tree[v].ch[1]];
return ret;
}
然后就是线段树板子了,时间复杂度
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=3e5+5;
int n,m,dy[N];ll ans[N];
struct Node{
int ag,sk,id;
bool operator < (const Node &rhs) const{
return ag<rhs.ag;
}
}a[N];
bool cmp(Node _1,Node _2){
return _1.sk<_2.sk;
}
struct Query{
int ag,nm,id;
bool operator < (const Query &rhs) const{
return ag<rhs.ag;
}
}q[N];
struct Segment_Tree{
struct Node{
bool ch[2];
int cnt[2];ll val[2];
}tree[N<<2];
inline int ls(int u){return u<<1;}
inline int rs(int u){return u<<1|1;}
inline Node push_up(int u,int v){
Node ret;
ret.ch[0]=tree[u].ch[tree[v].ch[0]];
ret.ch[1]=tree[u].ch[tree[v].ch[1]];
ret.cnt[0]=tree[v].cnt[0]+tree[u].cnt[tree[v].ch[0]];
ret.cnt[1]=tree[v].cnt[1]+tree[u].cnt[tree[v].ch[1]];
ret.val[0]=tree[v].val[0]+tree[u].val[tree[v].ch[0]];
ret.val[1]=tree[v].val[1]+tree[u].val[tree[v].ch[1]];
return ret;
}
inline void update(int u,int l,int r,int p,int x){
if(l==r){
tree[u].ch[0]=tree[u].cnt[0]=1;
tree[u].val[0]=x;return;
}
int mid=l+r>>1;
if(mid>=p)update(ls(u),l,mid,p,x);
else update(rs(u),mid+1,r,p,x);
tree[u]=push_up(ls(u),rs(u));
}
inline ll query(int u,int l,int r,int x,bool key){
if(l==r)return tree[u].val[key];
int mid=l+r>>1;
if(tree[rs(u)].cnt[key]>=x)return query(rs(u),mid+1,r,x,key);
return tree[rs(u)].val[key]+query(ls(u),l,mid,x-tree[rs(u)].cnt[key],tree[rs(u)].ch[key]);
}
}t;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].ag,&a[i].sk),a[i].id=i;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
dy[a[i].id]=i;
sort(a+1,a+n+1);
cin>>m;
for(int i=1;i<=m;i++)
scanf("%d%d",&q[i].ag,&q[i].nm),q[i].id=i;
sort(q+1,q+m+1);
for(int i=1,j=1;i<=m;i++){
while(j<=n&&a[j].ag<=q[i].ag)
t.update(1,1,n,dy[a[j].id],a[j].sk),j++;
ans[q[i].id]=t.query(1,1,n,q[i].nm,0);
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
return 0;
}