专栏文章
题解:P14293 [JOI2024 预选赛 R2] 购物 2 / Shopping 2
P14293题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minijj85
- 此快照首次捕获于
- 2025/12/02 02:59 3 个月前
- 此快照最后确认于
- 2025/12/02 02:59 3 个月前
Solution
我们发现如果不加促销的话,这道题就是道普通前缀和。
那么就从前缀和出发,我们现在想知道在 这段区间里,有多少个商品的种类为 。
我们可以考虑二分,对于每个种类我们开个 vector 来存这个种类的商品,并用这个 vector 维护每个种类个数前缀和。然后求区间内商品种类只需要二分就行了。
CPP#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+20;
int n,m,q;
struct node{
int id,sum;
};
int x,y;
int day,l,r;
vector<node> v[N];
int sum[N];
int check(int d,int L,int R){
int l=0,r=v[d].size()-1,res=-1,res1=-1;
while(l<=r){
int mid=l+r>>1;
if(v[d][mid].id<L) l=mid+1;
else r=mid-1,res=mid;
} //找出这段区间内种类为 d 的编号最大的
l=0,r=v[d].size()-1;
while(l<=r){
int mid=l+r>>1;
if(v[d][mid].id<=R) res1=mid,l=mid+1;
else r=mid-1;
} //找出这段区间内种类为 d 的编号最小的
if(res1==-1) return 0;
if(v[d][res1].id<L) return 0;
if(res<=0) return v[d][res1].sum;
else return v[d][res1].sum-v[d][res-1].sum; //前缀和
}
int k;
signed main(){
cin>>n>>m>>q;
for(int i=1;i<=n;i++){
cin>>y>>x;
sum[i]=sum[i-1]+y,k=v[x].size()-1;
if(k<0) k=y;
else k=v[x][k].sum+y;
v[x].push_back((node){i,k}); //这里维护每个种类的前缀和
}
for(int i=1;i<=q;i++){
cin>>day>>l>>r;
int ans=sum[r]-sum[l-1]-check(day,l,r)/2;
cout<<ans<<"\n";
}
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...