题目大意:
给你一个数组,给你如下几种操作:
s l r mod 查询区间【l,r】中模m等于mod的数字之和;
+ p r 将p位置的数加上r后模m;
- p r 将p位置的数减去r后模m;
解题思路:
一般进行区间查询,位置操作可以使用线段树或者树状数组解决(暂时只会树状数组);这题的特殊之处就在于要求模m等值;
由于m的值较小(m<10) 因此我们可以开一个二重的树状数组,第二重保存模m后的值;其余操作就是基本的树状~
#include <iostream> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <algorithm> #include <iterator> #include <queue> #include <cmath> #include <map> #include <cstdio> using namespace std; typedef long long ll; #define maxn 100007 #define INF 0x3f3f3f3f ll n,m,mod; ll a[maxn]; ll c[maxn][20]; int lowbit(int x) { return x&(-x); } void add(int pos,ll v,int mod) { // cout<<v<<" "<<mod<<"+++++++"<<endl; while(pos<=n) { c[pos][mod]+=v; pos+=lowbit(pos); } } ll ac_sum(int pos,int mod) { ll sum=0; while(pos>0) { //cout<<"++++"<<endl; sum+=c[pos][mod]; pos-=lowbit(pos); } return sum; } int main() { ios::sync_with_stdio(false); cin>>n>>m; for (int i=1;i<=n;i++) { //int a; cin>>a[i]; add(i,a[i],(a[i]%m)); } int k; cin>>k; while (k--) { string s; cin>>s; if (s[0]==‘s‘) { ll i,j,l; cin>>i>>j>>l; cout<<ac_sum(j,l)-ac_sum(i-1,l)<<endl; } else if (s[0]==‘+‘) { ll i,j; cin>>i>>j; add(i,-a[i],a[i]%m); a[i]+=j; add(i,a[i],a[i]%m); cout<<a[i]<<endl; } else if (s[0]==‘-‘) { ll i,j; cin>>i>>j; add(i,-a[i],a[i]%m); if (a[i]>=j) { a[i]-=j; } add(i,a[i],a[i]%m); cout<<a[i]<<endl; } } }
时间: 2024-10-02 10:16:26