hdu4027

来源:互联网 发布:kerberos源码 编辑:程序博客网 时间:2024/06/05 17:54

去年上海赛区网络赛的一道简单题,数据量很大,不过要捉住题目中的重点,就是每次更新是对这个区间的所有的数开平方,从2^64开平方一直开尽(由于是开方取整),所以开6次即可。即使是一个个点更新,复杂度也只不过是O(6N)。用COL[]纪录线段中的数据是不是被开尽,这样就节省了后面的无用功。另外注意的是x,y会颠倒。。因为题目中说的是between x and y显然没有交代大小关系。。附代码:

#include <iostream>#include <cmath>using namespace std;#define clear(a) memset(a,0,sizeof(a))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int N=100100;__int64 sum[N<<2],col[N<<2];void pushup(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];    col[rt]=col[rt<<1]&&col[rt<<1|1];}void build(int l,int r,int rt){    if (l==r)    {        scanf("%I64d",&sum[rt]);        return;    }    int m=(l+r)>>1;    build(lson);    build(rson);    pushup(rt);}__int64 query(int L,int R,int l,int r,int rt){    if (L<=l&&r<=R)    {        return sum[rt];    }    int m=(l+r)>>1;    __int64 ret=0;    if (L<=m) ret+=query(L,R,lson);    if (R>m) ret+=query(L,R,rson);    return ret;}void update(int L,int R,int l,int r,int rt){    if (l==r)    {        sum[rt]=sqrt(sum[rt]);        if (sum[rt]<=1) col[rt]=1;         return;      }    int m=(l+r)>>1;    if (L<=m&&!col[rt<<1]) update(L,R,lson);    if (R>m&&!col[rt<<1|1]) update(L,R,rson);    pushup(rt);}int main(){    int i,n,m,k=0;    while (scanf("%d",&n)!=EOF)    {        k++;          clear(sum);        clear(col);        build(1,n,1);        scanf("%d",&m);         printf("Case #%d:\n",k);        int z,x,y;        for (i=1;i<=m;i++)        {            scanf("%d%d%d",&z,&x,&y);            if (x>y)             {                int tmp=x;                x=y;                y=tmp;            }            if (z==1)            {                __int64 s=query(x,y,1,n,1);                printf("%I64d\n",s);            }            else update(x,y,1,n,1);              }        printf("\n");    }    return 0;}


 

原创粉丝点击