南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的。
小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧。
南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新增的杀敌数。
5 6 1 2 3 4 5 QUERY 1 3 ADD 1 2 QUERY 1 3 ADD 2 3 QUERY 1 2 QUERY 1 5
6 8 8 20
开始一看题马上想到用线段数做,可是苦逼的菜鸟只会打模板,超时~~~,心碎。。杭电上“I hate it”也是超时,,只好去学树状数组,,不过看了这么多大神的博客发现树状数组的局限性比较小,对于这道题还是可以的;
超时代码: (线段数)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<string> using namespace std; const int N=1000000+10; struct node { int l,r,n; }a[N<<2]; void build(int l,int r,int k) { int mid; if(l==r) { a[k].l=a[k].r=l; a[k].n=0; return ; } mid=(l+r)>>1; a[k].l=l,a[k].r=r; build(l,mid,2*k);//深层构建左子树; build(mid+1,r,2*k+1);//深层构建右子树; } void add(int d,int n,int k)//插入函数; { int mid; if(a[k].l==a[k].r&&a[k].r==d) { a[k].n+=n; return ; } mid=(a[k].l+a[k].r)>>1; if(d<=mid) add(d,n,2*k); else if(d>mid) add(d,n,2*k+1); a[k].n=a[k*2].n+a[k*2+1].n;//回溯,使父亲节点储存两个儿子节点的值,便于查找; } int sum; void query(int l,int r,int k) { int mid; if(a[k].l==l&&a[k].r==r) { sum+=a[k].n; return ; } mid=(a[k].l+a[k].r)>>1; if(r<=mid) query(l,r,2*k);<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">往左子树查询;</span>
<span style="font-size:18px;"> else if(l>mid) query(l,r,2*k+1); else { query(l,mid,2*k); query(mid+1,r,2*k+1); } } int main() { int n,m,x; int a,b,i; char s[10]; scanf("%d%d",&n,&m); build(1,n,1); for(i=1; i<=n; i++) { scanf("%d",&x); add(i,x,1); } while(m--) { scanf("%s%d%d",s,&a,&b); if(s[0]=='Q') { sum=0; query(a,b,1); printf("%d\n",sum); } else add(a,b,1); } return 0; } 为何会超时??????</span>
AC代码:(树状数组)
#include<bits/stdc++.h> using namespace std; const int N=1000000+10; int a[N],c[N]; int lowbit(int i) { return i&(i^(i-1)); } void getC(int *a,int n) { for(int i=1; i<=n; i++) { int k=lowbit(i); c[i]=0; for(int j=i-k+1; j<=i; j++) c[i]+=a[j]; } } void update(int i,int x,int n) { a[i]+=x; while(i<=n) { c[i]+=x; i+=lowbit(i); } } int sum(int i) { int x=0; while(i) { x+=c[i]; i-=lowbit(i); } return x; } void query(int x,int y) { printf("%d\n",sum(y)-sum(x)+a[x]); } int main() { int n,m,i; char s[10]; scanf("%d%d",&n,&m); for(i=1; i<=n; i++) scanf("%d",&a[i]); getC(a,n); while(m--) { int a,b; scanf("%s",s); scanf("%d%d",&a,&b); if(s[0]=='Q') query(a,b); else update(a,b,n); } return 0; }