hdu 1166 敌兵布阵 + Dairy

来源:互联网 发布:淘宝店铺链接转换微信 编辑:程序博客网 时间:2024/06/04 17:50

Today is 4.30,the second day in 2S.
遇见了一个十分humorous的把妹老师。嗯南方人。所化四泽阳的。

说正事:
今天第一题,两种解,打算好好写写,但是据说我写的东西跟八级阅读题一样。。【【【黑线

第一种方法:

树状数组。

其神奇所在,大概是lowbit数组。
大多数树状数组都是这个图

由图可知,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 50005int 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;  } /*1101 2 3 4 5 6 7 8 9 10Query 1 3Add 3 6Query 2 7Sub 10 2Add 6 3Query 3 10End  */

第二种方法:

线段树:
没什么解释的?

直接看好了

#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));            }        }    }}

啦啦啦,拖到现在才写完,马上就要上课了。

0 0
原创粉丝点击