洛谷题解洛谷题解题解:P10401 「XSOI-R1」区间操作
xyx404
思路:
使用前缀和,考虑到输入的询问范围可能会有 l 相同,所以先用一个结构体把输入的 l 和 r 和输入的顺序存起来,然后进行排序哪个左端点更小,如果同时左端点相同,那么比较哪个右端点更小。
在 l 相等时,我们可以直接按照上一个的答案往下搜这样重复的部分就不用重复计算历遍了。
为什么可以直接按照上一个的答案往下搜,因为我们在一开始排过序,只要这个结构体排完序后在前一个结构体后面,并且 l 相同,那么后面的结构体的 r 一定大于等于前面的结构体的 r,所以可以直接按照上一个的答案往下搜。
当 l 不相等时,就正常地直接历遍,然后存答案就可以了。
完整代码:
#include<bits/stdc++.h> using namespace std; #define ull unsigned long long #define LL long long ull tamp; const int MAXN=10001; const int MAXQ=1000001; ull n,q; ull sum[MAXN]; ull a[100010]; struct node{ ull l,r,id,ans; }wt[MAXQ]; bool cmp_id(node x,node y){ return x.id<y.id; } bool cmp_lr(node x,node y){ if(x.l==y.l)return x.r<y.r; return x.l<y.l; } void find(){ ull su; for(ull i=1;i<=q;i++){ if(wt[i].l!=wt[i-1].l){ su=a[wt[i].l]; for(int j=wt[i].l+1;j<=wt[i].r;j++){ su^=(sum[j]-sum[wt[i].l-1]); } wt[i].ans=su; } else{ if(wt[i].l==wt[i-1].l&&wt[i].r==wt[i-1].r){ wt[i].ans=su; } else{ for(ull j=wt[i-1].r+1;j<=wt[i].r;j++){ su^=(sum[j]-sum[wt[i].l-1]); } wt[i].ans=su; } } } } int main(){ cin>>n>>q; for(ull i=1;i<=n;i++){ cin>>a[i]; sum[i]=sum[i-1]+a[i]; } for(ull i=1;i<=q;i++)cin>>wt[i].l>>wt[i].r,wt[i].id=i; sort(wt+1,wt+1+q,cmp_lr); find(); sort(wt+1,wt+1+q,cmp_id); for(ull i=1;i<=q;i++)cout<<wt[i].ans<<"\n"; return 0; }
|