hdu5481

来源:互联网 发布:mysql my.cnf 路径 编辑:程序博客网 时间:2024/06/16 13:49

一开始尝试用线段树,结果超时。

超时的代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#define N 200010#define MOD 1000000007struct node{    int l,r;    int cou;};int num[N];int l[N],r[N];int m;struct node tree[4*N];int alll,allr;void lisanhua(int n){    sort(num,num+n);    m=unique(num,num+n)-num;    return;}void create(int root,int l,int r){    if(l+1==r){        tree[root].l=l;        tree[root].r=r;        tree[root].cou=0;        return;    }    else{        int middle=(l+r)>>1;        create(root<<1,l,middle);        create((root<<1)+1,middle,r);        tree[root].l=l;        tree[root].r=r;        tree[root].cou=0;        return;    }}void push_down(int root){    if(tree[root].cou){        tree[root<<1].cou+=tree[root].cou;        tree[(root<<1)+1].cou+=tree[root].cou;        tree[root].cou=0;    }    return;}int query(int root,int l,int r){    if(l+1==r){        return tree[root].cou;    }    else{        int middle=(r+l)>>1;        push_down(root);        if(allr<=middle){            return query(root<<1,l,middle);        }        else{            return query((root<<1)+1,middle,r);        }    }}void add(int root,int l,int r){    if(alll<=l&&allr>=r){//这里想错了,所以写成了 l<=alll&&r>=allr        tree[root].cou+=1;        return;    }    else{        int middle=(l+r)>>1;        if(alll<middle){            add(root<<1,l,middle);        }        if(allr>middle){            add((root<<1)+1,middle,r);        }        return;    }}int hush(int n){    return lower_bound(num,num+m,n)-num+1;}long long int km(long long int x,long long int y){    long long int ans=1;    while(y){        if(y%2){            y=y/2;            ans=ans*x%MOD;        }        y=y/2;        x=x*x%MOD;    }    return ans;}int main(){    int t;    int n;    int numcou;    long long int ans;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        numcou=0;        for(int i=0;i<n;i++){            scanf("%d%d",&l[i],&r[i]);            num[numcou++]=l[i];            num[numcou++]=r[i];        }        lisanhua(2*n);        create(1,1,m);        ans=0;        //printf("%d\n",m);        for(int i=0;i<n;i++){            int templ=hush(l[i]);            int tempr=hush(r[i]);            for(int j=templ+1;j<=tempr;j++){                alll=j-1;                allr=j;                int tempcou=query(1,1,m);                //printf("%d %d %d %d %d\n",tempcou,num[j-1],num[j-2],j-1,j);                ans=(ans+km(2,i-tempcou)*km(2,n-i-1)%MOD*(num[j-1]-num[j-2])%MOD)%MOD;            }            alll=templ;            allr=tempr;            //printf("%d %d %d %d\n",l[i],r[i],alll,allr);            add(1,1,m);        }        printf("%lld\n",ans);    }}

部分优化后,还是超时。

超时的代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#define N 200010#define MOD 1000000007int cou[N*4];int num[N];int l[N],r[N];int m;int alll,allr;long long int mi[N];void lisanhua(int n){    sort(num,num+n);    m=unique(num,num+n)-num;    return;}void create(int root,int l,int r){    if(l+1==r){        cou[root]=0;        return;    }    else{        int middle=(l+r)>>1;        create(root<<1,l,middle);        create((root<<1)+1,middle,r);        cou[root]=0;        return;    }}void push_down(int root){    if(cou[root]){        cou[root<<1]+=cou[root];        cou[(root<<1)+1]+=cou[root];        cou[root]=0;    }    return;}int query(int root,int l,int r){    if(l+1==r){        return cou[root];    }    else{        int middle=(r+l)>>1;        push_down(root);        if(allr<=middle){            return query(root<<1,l,middle);        }        else{            return query((root<<1)+1,middle,r);        }    }}void add(int root,int l,int r){    if(alll<=l&&allr>=r){        cou[root]+=1;        return;    }    else{        int middle=(l+r)>>1;        if(alll<middle){            add(root<<1,l,middle);        }        if(allr>middle){            add((root<<1)+1,middle,r);        }        return;    }}int hush(int n){    return lower_bound(num,num+m,n)-num+1;}int main(){    int t;    int n;    int numcou;    long long int ans;    mi[0]=1;    for(int i=1;i<N;i++){        mi[i]=mi[i-1]*2%MOD;    }    scanf("%d",&t);    while(t--){        scanf("%d",&n);        numcou=0;        for(int i=0;i<n;i++){            scanf("%d%d",&l[i],&r[i]);            num[numcou++]=l[i];            num[numcou++]=r[i];        }        lisanhua(2*n);        create(1,1,m);        ans=0;        //printf("%d\n",m);        for(int i=0;i<n;i++){            int templ=hush(l[i]);            int tempr=hush(r[i]);            for(int j=templ+1;j<=tempr;j++){                alll=j-1;                allr=j;                int tempcou=query(1,1,m);                //printf("%d %d %d %d %d\n",tempcou,num[j-1],num[j-2],j-1,j);                ans=(ans+mi[i-tempcou]*mi[n-i-1]%MOD*(num[j-1]-num[j-2])%MOD)%MOD;            }            alll=templ;            allr=tempr;            //printf("%d %d %d %d\n",l[i],r[i],alll,allr);            add(1,1,m);        }        printf("%lld\n",ans);    }}

想到可能是每一个区间都遍历一遍,会很超时,于是将计算答案留到最后,一起计算,最后整个从头到尾遍历一遍所有区间的并集就可以了。

所以整体的思路是:

每个单位段,比如说(1,2),(100,101),假设有这个单元段的区间是x个,总共是n个,那么这个单元段的贡献是 (2^x-1)*2^(n-x)。因为 l 和 r 的范围比较大,所以可以离散化后再做。

ac的代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#define N 200010#define MOD 1000000007int cou[N*4];int num[N];int l[N],r[N];int m;int n;int alll,allr;long long int mi[N];long long int ans;void lisanhua(int n){    sort(num,num+n);    m=unique(num,num+n)-num;    return;}void create(int root,int l,int r){    if(l+1==r){        cou[root]=0;        return;    }    else{        int middle=(l+r)>>1;        create(root<<1,l,middle);        create((root<<1)+1,middle,r);        cou[root]=0;        return;    }}void push_down(int root){    if(cou[root]){        cou[root<<1]+=cou[root];        cou[(root<<1)+1]+=cou[root];        cou[root]=0;    }    return;}int query(int root,int l,int r){    if(l+1==r){        return cou[root];    }    else{        int middle=(r+l)>>1;        push_down(root);        if(allr<=middle){            return query(root<<1,l,middle);        }        else{            return query((root<<1)+1,middle,r);        }    }}void add(int root,int l,int r){    if(alll<=l&&allr>=r){        cou[root]+=1;        return;    }    else{        int middle=(l+r)>>1;        if(alll<middle){            add(root<<1,l,middle);        }        if(allr>middle){            add((root<<1)+1,middle,r);        }        return;    }}int hush(int n){    return lower_bound(num,num+m,n)-num+1;}void nodepush_down(int root,int l,int r){    if(l+1==r){        int temp=cou[root];        ans=(ans+((mi[temp]-1)%MOD+MOD)%MOD*mi[n-temp]%MOD*(num[r-1]-num[l-1])%MOD)%MOD;        return;    }    else{        int middle=(l+r)>>1;        push_down(root);        nodepush_down(root<<1,l,middle);        nodepush_down((root<<1)+1,middle,r);        return;    }}int main(){    int t;    int numcou;    mi[0]=1;    for(int i=1;i<N;i++){        mi[i]=mi[i-1]*2%MOD;    }    scanf("%d",&t);    while(t--){        scanf("%d",&n);        numcou=0;        for(int i=0;i<n;i++){            scanf("%d%d",&l[i],&r[i]);            num[numcou++]=l[i];            num[numcou++]=r[i];        }        lisanhua(2*n);        create(1,1,m);        //printf("%d\n",m);        for(int i=0;i<n;i++){            alll=hush(l[i]);            allr=hush(r[i]);            add(1,1,m);        }        ans=0;        nodepush_down(1,1,m);        printf("%lld\n",ans);    }}


参考链接:

http://blog.csdn.net/u014679804/article/details/48770245
看别人的思路更简单,是在区间的开始+1,在区间的结束-1,把所有的区间加进去后,最后求答案,是再遍历。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝不能用花呗怎么办 淘宝号给冻结了怎么办 淘宝买家号封了怎么办 拼多多商家盗图怎么办 被拼多多盗图了怎么办 淘宝盗用图片被投诉怎么办 淘宝别人盗用我的图片怎么办 淘宝盗图申诉原图过大怎么办 淘宝别人举报我盗用图片怎么办 淘宝卖家被投诉盗图怎么办 淘宝卖家被投诉卖假货怎么办 淘宝买到假货卖家不承认怎么办 被投诉盗图扣2分怎么办 拼多多盗淘宝图怎么办 微信视频清理了怎么办 牛仔短裤买大了怎么办 淘宝图片打开变大了怎么办 同城换公司社保怎么办 劳务不给交社保怎么办 好多工厂外包工不交社保怎么办 外包公司没有交社保怎么办 外包公司不给交社保怎么办 银行取100万现金怎么办 给老外发警告信后怎么办 照片上传是歪的怎么办 日亚不能直邮的怎么办 电话信息被卖了怎么办 被亚马逊跟卖了怎么办 玉米出芽后土壤不够湿怎么办 雨伞请输入授权码怎么办 网页放手机端后看不了怎么办 微信收款码存在违法行为怎么办 tst优惠码密码忘了怎么办 扩展器登录不上怎么办 微信学法小程序积分不更新怎么办 开发商不给办房产证怎么办 传淘宝产品规格不匹配怎么办 刚买的手机想退怎么办 空调主机空间不足不散热怎么办 lol网速快延迟高怎么办 4g手机延迟高怎么办