【codevs 1080~1082】线段树练习重做

来源:互联网 发布:php stdclass new 编辑:程序博客网 时间:2024/05/16 15:41

为了纪念在机房睡觉的第一个晚上~
今晚上开分块~
顺带看看今晚能更多少
(2016年3月18日21:03:28)

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>using namespace std;const int MAXN = 1000000 + 5;int n,m;int num[MAXN];int sum[MAXN];int M;void init(){    M = sqrt(n) + 1;    for(int i = 0;i < n;i ++)        sum[i / M] += num[i];    return;}void change(int x,int y){    num[x] += y;    sum[x / M] += y;    return;}int ask(int x,int y){    int ans = 0;    while(x % M && x < y)        ans += num[x ++];    while(y % M && y > x)        ans += num[y --];    ans += num[y];    while(x < y)    {        ans += sum[x / M];        x += M;    }    return ans;}int q,a,b,v;int main(){    scanf("%d",&n);    for(int i = 0;i < n;i ++)        scanf("%d",&num[i]);    init();    scanf("%d",&m);    for(int i = 1;i <= m;i ++)    {        scanf("%d",&q);        switch(q)        {            case 1:scanf("%d %d",&a,&v);change(a - 1,v);break;            case 2:scanf("%d %d",&a,&b);printf("%d\n",ask(a - 1,b - 1));break;        }    }    return 0;}

第二题~
依然用分块~
记得打标记
(2016年3月18日21:17:28)

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>using namespace std;const int MAXN = 1000000 + 5;int n,m;int num[MAXN];int sum[MAXN];int add[MAXN];int M;void init(){    M = sqrt(n) + 1;    for(int i = 0;i < n;i ++)        sum[i / M] += num[i];    return;}void change(int x,int y,int v){    while(x % M && x < y)        num[x ++] += v;    while(y % M && y > x)        num[y --] += v;    num[y] += v;    while(x < y)    {        add[x / M] += v;        x += M;    }    return;}int ask(int x){    return num[x] + add[x / M];}int q,a,b,v;int main(){    scanf("%d",&n);    for(int i = 0;i < n;i ++)        scanf("%d",&num[i]);    init();    scanf("%d",&m);    for(int i = 1;i <= m;i ++)    {        scanf("%d",&q);        switch(q)        {            case 1:scanf("%d %d %d",&a,&b,&v);change(a - 1,b - 1,v);break;            case 2:scanf("%d",&a);printf("%d\n",ask(a - 1));break;        }    }    return 0;}

第三题
总结出来的经验就是想好什么是针对块的,什么是针对元素的……
换句话说就是sum[x / M]别写成sum[x]了……
DQS:“小兔子你个傻x”
2016年3月18日21:41:22

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>using namespace std;typedef long long LL;const int MAXN = 1000000 + 5;int n,m;LL num[MAXN],sum[MAXN],add[MAXN];int M;void init(){    M = sqrt(n) + 1;    for(int i = 0;i < n;i ++)        sum[i / M] += num[i];    return;}void change(int x,int y,LL v){    while(x % M && x < y)    {        num[x] += v;        sum[x / M] += v;        x ++;    }    while(y % M && y > x)    {        num[y] += v;        sum[y / M] += v;        y --;    }    num[y] += v;    sum[y / M] += v;    while(x < y)    {        add[x / M] += v;        sum[x / M] += v * M;        x += M;    }    return;}LL ask(int x,int y){    LL ans = 0;    while(x % M && x < y)        ans += num[x] + add[x / M],x ++;    while(y % M && y > x)        ans += num[y] + add[y / M],y --;    ans += num[y] + add[y / M];    while(x < y)    {        ans += sum[x / M];        x += M;    }    return ans;}int q,a,b;LL v;int main(){    scanf("%d",&n);    for(int i = 0;i < n;i ++)        scanf("%lld",&num[i]);    init();    scanf("%d",&m);    for(int i = 1;i <= m;i ++)    {        scanf("%d",&q);        switch(q)        {            case 1:scanf("%d %d %lld",&a,&b,&v);change(a - 1,b - 1,v);break;            case 2:scanf("%d %d",&a,&b);printf("%lld\n",ask(a - 1,b - 1));break;        }    }    return 0;}
0 0