NYOJ1217 GLaDOS的耳机(线段树,区间染色)

描述

    GLaDOS是个耳机控。对于他来说,已经不满足于只是听出供电设备是水电、核电还是火电了。GLaDOS有更大的目标,他想听出宇宙中最神秘的代号为"Y_A_FL"的声音。为了实现这个目的,GLaDOS决定为他的耳机加工升级。但是笨手笨脚的GLaDOS表示加工升级神马的太困难了。于是GLaDOS想请JX为他解决这个难题,而懒得不能再懒得JX又把这个难题交给了你,你能帮这两个二货解决这个问题么?

    现在,给你一个n,表示耳机上有n个点,相邻的每两个点间距为1单位长度。从左往右,每个点的编号分别为1,2,3...n。GLaDOS想要对这条耳机线进行m次操作。对于这条耳机线,GLaDOS有两种操作:
     ⊙ 1 L R c d代表着GLaDOS想要为这条耳机线从L点到R点的这段区间上涂一层金属漆(1<=L,R<=n)金属漆的颜色为c(0<=c<=40000),新涂的金属漆会将原有的金属漆覆盖,每单位长度的金属漆重量为d(0<d<=1000)(最初耳机线的重量为0,没有颜色)。
     ⊙ 2 L R 代表着GLaDOS想要知道耳机线在L点到R点这段区间内的重量。

在m次操作结束之后,GLaDOS想知道这根耳机线的总重量和这根耳机线上颜色的种数。

输入

输入包含多组数据(最多11组) 每组数据的第一行是两个整数n,m(2<=n,m<=80000)分别表示耳机长度和GLaDOS的操作次数。
接着是m行,每行一个操作。

输出

每组数据 对于每个操作2,你都将输出1个整数,代表着在L到R这段区间内的耳机线的重量。 每组数据的最后一行,输出耳机的总重量和颜色种数。

样例输入

1000 6
1 100 1000 1 10
2 500 621
1 7 842 2 10
2 500 621
1 100 347 3 23
2 120 217

样例输出

1210
2420
4171
23031 3

思路

利用两个lazy数组,一个标记颜色,另一个维护和,因为这不是对点进行操作,而是对于每一段进行操作,所以要建树的时候对于区间[0,n-1]建树,具体看代码

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include<list>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f3f
typedef long long ll;
const ll N=8e4+100;
ll color[N<<2],lazy[N<<2],sum[N<<2],vis[N<<2],cnt;
void pushup(ll rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(ll rt,ll m)
{
    if(lazy[rt])
    {
        color[rt<<1]=color[rt<<1|1]=color[rt];
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        sum[rt<<1]+=lazy[rt]*(m-(m>>1));
        sum[rt<<1|1]+=lazy[rt]*(m>>1);
        color[rt]=-1;
        lazy[rt]=0;
    }
}
void build(ll l,ll r,ll rt)
{
    color[rt]=-1;
    lazy[rt]=0;
    sum[rt]=0;
    if(l==r) return;
    ll m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(ll L,ll R,ll c,ll d,ll l,ll r,ll rt)
{
    if(L<=l&&r<=R)
    {
        color[rt]=c;
        lazy[rt]+=d;
        sum[rt]+=(r-l+1)*d;
        return;
    }
    pushdown(rt,r-l+1);
    ll m=(l+r)>>1;
    if(L<=m) update(L,R,c,d,lson);
    if(R>m) update(L,R,c,d,rson);
    pushup(rt);
}
ll query(ll L,ll R,ll l,ll r,ll rt)
{
    if(L<=l&&r<=R)
    {
        return sum[rt];
    }
    pushdown(rt,r-l+1);
    ll m=(l+r)>>1;
    ll ans=0;
    if(L<=m) ans+=query(L,R,lson);
    if(R>m) ans+=query(L,R,rson);
    pushup(rt);
    return ans;
}
void queryc(ll L,ll R,ll l,ll r,ll rt)
{
    if(color[rt]!=-1)
    {
        if(!vis[color[rt]])
        {
            cnt++;
            vis[color[rt]]=1;
            return;
        }
    }
    if(l==r) return;
    pushdown(rt,r-l+1);
    ll m=(l+r)>>1;
    if(L<=m) queryc(L,R,lson);
    if(R>m) queryc(L,R,rson);
    pushup(rt);
}
int main()
{
    ll n,m,op,l,r,c,d;
    while(~scanf("%lld%lld",&n,&m))
    {
        mem(vis,0);
        cnt=0;
        build(1,n-1,1);
        while(m--)
        {
            scanf("%lld%lld%lld",&op,&l,&r);
            if(op==1)
            {
                scanf("%lld%lld",&c,&d);
                update(l,r-1,c,d,1,n-1,1);
            }
            else
            {
                printf("%lld\n",query(l,r-1,1,n-1,1));
            }
        }
        queryc(1,n-1,1,n-1,1);
        printf("%lld %lld\n",sum[1],cnt);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/80189860
今日推荐