1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End
Case 1: 6 33 59
这题是zkw线段树中单点修改与区间查询的一般方法:
M的计算 显然最后一行是:
但是我们求和值是不能求(0,M-1),(zkw线段树不支持首尾查询)
我们查询的应该是开区间(a,b) (这样的目的是保证不出现当前无法判定是否取-
原理:在左边时左边不取,而若右边不为t(s^t≠1),则必取.
在右边时右边不取,而若左边不为s(s^t≠1),则必取.
M=1;while (M-2<n) M<<=1;
由于char s[]为数组,无法直接比较
需要用 strcmp(string a,string a)==0 判定
它是字符串的cmp 返回字典序比较情况
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<cctype> #include<iostream> using namespace std; #define MAXN (50000+10) #define MAXAi (50+10) int n,m,k,M,tt,t[MAXN*5]; char s[50]; int main() { // freopen("Hdu1166.in","r",stdin); scanf("%d",&tt); for (int k=1;k<=tt;k++) { printf("Case %d:\n",k); scanf("%d",&n); memset(t,0,sizeof(t)); M=1;while (M-2<n) M<<=1; for (int i=M+1;i<=M+n;i++) scanf("%d",&t[i]); for (int i=M;i>=1;i--) t[i]=t[i<<1]+t[(i<<1)^1]; while (scanf("%s",s)!=EOF) { if (!strcmp(s,"End")) break; int p1,p2; scanf("%d%d",&p1,&p2); if (s[0]=='Q') { int ans=0; p1--;p2++;p1+=M;p2+=M; while (p1^p2^1>0) { if (~p1&1) ans+=t[p1+1]; if (p2&1) ans+=t[p2-1]; p1>>=1;p2>>=1; } cout<<ans<<endl; continue; } else { p1+=M; if (s[0]=='A') t[p1]+=p2; else t[p1]-=p2; for (p1/=2;p1;p1/=2) { t[p1]=t[p1<<1]+t[(p1<<1)^1]; } } } } return 0; }