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

题目链接


线段树 区间合并 成段更新题,什么鬼,模拟它,不断地成段更新,最后好不容易调试出来了,发现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 | 1
const 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值