九度OJ 题目1496:数列区间 (线段树 区间合并 +成段更新)

来源:互联网 发布:董宇阳,知乎 编辑:程序博客网 时间:2024/05/01 02:37

题目链接


线段树 区间合并 成段更新题,什么鬼,模拟它,不断地成段更新,最后好不容易调试出来了,发现TLE,而且只超了80ms,什么鬼!!!

然后小小地优化了一下,如果前面的一些区间被最后的一个区间完全覆盖的话,就没必要更新它。小小的优化了一下,就过了,是飘过。。。。

前前后后搞了3个小时吧。

#include <cstdio>#include <cstring>#include <cctype>#include <algorithm>using namespace std;#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1const int maxn = 1000005;int lsum[maxn<<2] , rsum[maxn<<2] , msum[maxn<<2],ln[maxn<<2],rn[maxn<<2];int cover[maxn<<2];int x[maxn],y[maxn],ansx[maxn],ansy[maxn];int cnt=0;struct node{    int x,y;}a[100005],ans[100005];void PushDown(int rt,int m){    if (cover[rt] != -1)    {        cover[rt<<1] = cover[rt<<1|1] = cover[rt];        ln[rt<<1]=rn[rt<<1]=cover[rt];        ln[rt<<1|1]=rn[rt<<1|1]=cover[rt];        msum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] =m - (m >> 1);        msum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = (m >> 1);        //printf("%d:  rt lsum=%d rsum=%d msum=%d ln=%d rn=%d cover=%d\n",cnt++,lsum[rt],rsum[rt],msum[rt],ln[rt],rn[rt],cover[rt]);        //printf("%d: lson lsum=%d rsum=%d msum=%d ln=%d rn=%d cover=%d\n",cnt++,lsum[rt<<1],rsum[rt<<1],msum[rt<<1],ln[rt<<1],rn[rt<<1],cover[rt<<1]);       // printf("%d: rson lsum=%d rsum=%d msum=%d ln=%d rn=%d cover=%d\n",cnt++,lsum[rt<<1|1],rsum[rt<<1|1],msum[rt<<1|1],ln[rt<<1|1],rn[rt<<1|1],cover[rt<<1|1]);        cover[rt] = -1;    }}void PushUp(int rt,int m){    lsum[rt] = lsum[rt<<1];rsum[rt] = rsum[rt<<1|1];    msum[rt] = max(msum[rt<<1],msum[rt<<1|1]);    ln[rt]=ln[rt<<1];rn[rt]=rn[rt<<1|1];    if(rn[rt<<1]==ln[rt<<1|1]&&rn[rt<<1]&&ln[rt<<1|1])    {        if (lsum[rt] == m - (m >> 1)) lsum[rt] += lsum[rt<<1|1];        if (rsum[rt] == (m >> 1)) rsum[rt] += rsum[rt<<1];        msum[rt] = max(lsum[rt<<1|1] + rsum[rt<<1] , msum[rt]);    }}void build(int l,int r,int rt){    msum[rt] = lsum[rt] = rsum[rt] = 0;//r - l + 1;    ln[rt]=rn[rt]=0;    cover[rt] = -1;    if (l == r) return ;    int m = (l + r) >> 1;    build(lson);    build(rson);}void update(int L,int R,int c,int l,int r,int rt){    if (L <= l && r <= R)    {        msum[rt] = lsum[rt] = rsum[rt] = r - l + 1;        cover[rt] = c;        ln[rt]=rn[rt]=c;        //printf("%d: [%d %d] lsum=%d rsum=%d msum=%d ln=%d rn=%d cover=%d\n",cnt++,l,r,lsum[rt],rsum[rt],msum[rt],ln[rt],rn[rt],cover[rt]);        return ;    }    PushDown(rt , r - l + 1);    int m = (l + r) >> 1;    if (L <= m) update(L , R , c , lson);    if (m < R) update(L , R , c , rson);    PushUp(rt , r - l + 1);     //printf("%d: [%d %d] lsum=%d rsum=%d msum=%d ln=%d rn=%d cover=%d\n",cnt++,l,r,lsum[rt],rsum[rt],msum[rt],ln[rt],rn[rt],cover[rt]);}int Scan(){int res = 0, ch, flag = 0;if((ch = getchar()) == '-')//判断正负flag = 1;else if(ch >= '0' && ch <= '9')//得到完整的数res = ch - '0';while((ch = getchar()) >= '0' && ch <= '9' )res = res * 10 + ch - '0';return flag ? -res : res;}int main(){    int n , m;    //freopen("in.txt","r",stdin);    //while(n=Scan())    while(~scanf("%d%d",&n,&m))    {        //m=Scan();        build(1 , n , 1);        for(int i=1;i<=m;i++) scanf("%d%d",&a[i].x,&a[i].y);        int p=1,l=a[m].x,r=a[m].y;        if(m) ans[p++]=a[m];        for(int i=m;i>=1;i--)            if(a[i].x<=l||a[i].y>=r) ans[p++]=a[i];        for(int i=p-1,id=1;i>=1;i--)        {            //printf("update[%d,%d]\n",ans[i].x,ans[i].y);            update(ans[i].x,ans[i].y,id++,1,n,1);        }        //puts("yes");        printf("%d\n",msum[1]);    }    return 0;}


0 0
原创粉丝点击