Today is 4.30,the second day in 2S.
遇见了一个十分humorous的把妹老师。嗯南方人。所化四泽阳的。
说正事:
今天第一题,两种解,打算好好写写,但是据说我写的东西跟八级阅读题一样。。【【【黑线
树状数组。
由图可知,c1=a1,c2=a1+a2,c3=a3,c4=a1+a2+a3+a4……
一次类推可知,i是奇数时,ai=ci;i是偶数是(c6=a5+a6),要看i里含2
的几次幂的因数。比如c4里是2的2次幂,所以是a1+a2+a3+a4;c6只含2,所以是a5+a6; 所以我们有有公式:cn=a(n-2^k+1)+………+an(其中 k 为 n 的二进制表示中从右往左数的 0 的个数)。 eg:6的二进制是110,那就是6-2^1+1,所以就是a5+a6。
2^k怎么求呢?
int lowbit(int x){
return x&(-x);
}
如上,其实是x&(~(x-1))…..
举个例子:
6 110
~(5) 010
6&~(5) 010 ==2 !
剩下的简单的多了,一个是插入操作,还有一个修改。
看代码好了
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 50005
int n;
int a[N],c[N];
int lowbit(int x){
return x&(-x);
}
void add(int i,int w){
while(i<=n){
c[i]+=w;
i=i+lowbit(i); //增加是要往后跳的!!
}
}
int sum(int i){
int sum=0;
while(i>0){
sum+=c[i];
i=i-lowbit(i); //求和则是往前。
}
return sum;
}
int main()
{
int t,i,tmp,x,y,cases=1;
char op[100];
scanf("%d",&t);
while(t--)
{
printf("Case %d:\n",cases++);
memset(a,0,sizeof(a));
memset(c,0,sizeof(c)); //记得要清空数组!!
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&tmp);
add(i,tmp);
}
while(scanf("%s",op)&& op[0]!='E')
{
scanf("%d%d",&x,&y);
if(op[0]=='A')
add(x,y);
else if(op[0]=='S')
add(x,-y);
else
printf("%d\n",sum(y)-sum(x-1));
}
}
return 0;
}
/*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 */
第二种方法:
–
线段树:
没什么解释的?
直接看好了
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
struct Line{
int left,right;
int val;
}line[200001];
int n,ans,jy,cases=1;
int c[200001];
char op[11];
void build(int l,int r,int num){
if(l == r)
{
scanf("%d",&line[num].val);
return;
}
line[num].left=l;
line[num].right=r;
int mid=(l+r)/2;
build(l,mid,2*num);
build(mid+1,r,2*num+1);
line[num].val=line[num*2].val+line[num*2+1].val;//更新父亲节点
}
void modify(int a,int b,int s,int t,int num){
if(s == t){
line[num].val+=b;
return;
}
int mid=(s+t)/2;
if(a<=mid) modify(a,b,s,mid,num*2);
else modify(a,b,mid+1,t,num*2+1);
line[num].val=line[num*2].val+line[num*2+1].val;
}
int query(int a,int b,int s,int t,int num){
// printf("%d %d %d\n",a,b,num);
if(a<=s && b>=t){
return line[num].val;
//printf("lal %d\n",line[num].val);
}
int mid=(s+t)/2;
int res=0;
if(a<=mid) res+=query(a,b,s,mid,num*2);
//printf("%d\n",res);
if(b>mid) res+=query(a,b,mid+1,t,num*2+1);
//printf("%d\n",res);
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
printf("Case %d:\n",cases++);
scanf("%d",&n);
build(1,n,1);
/* for(int i=1;i<=10;i++){ printf("%d \n",line[i].val); }*/
int x,y;
//while(scanf("%s",op) && op[0]!='E'){
while(1){
scanf("%s",op);
if(op[0] == 'E') break;
//scanf("%d%d",&x,&y);
if(op[0] == 'A') {
scanf("%d%d",&x,&y);
modify(x,y,1,n,1);
}
if(op[0] == 'S') {
scanf("%d%d",&x,&y);
modify(x,-y,1,n,1);
}
if(op[0] == 'Q'){
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y,1,n,1));
}
}
}
}
啦啦啦,拖到现在才写完,马上就要上课了。