计蒜客习题:木桩涂涂看

问题描述

n 个木桩排成一排,从左到右依次编号为 1,2,3…n。每次给定 2 个整数 a,b(a≤b),蒜头君便骑上他的电动车从木桩 a 开始到木桩 b 依次给每个木桩涂一次颜色。但是 n 次以后 lele 已经忘记了第 i 个木桩已经涂过几次颜色了,你能帮他算出每个木桩被涂过几次颜色吗?
输入格式
第一行是一个整数 n(n≤100000)。
接下来的 n 行,每行包括两个整数 a, b (1≤a≤b≤n)。

输出格式
n 个整数,第 i 个数代表第 i 个木桩总共被涂色的次数。
样例输入

3
1 1
1 2
1 3

样例输出

3 2 1

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_N=(1e5)+50;
int s[MAX_N*4];
int lazy[MAX_N*4];

void up(int p){
    s[p]=s[p*2]+s[p*2+1];
    return;
} 

void down(int p,int l,int r){
    if(lazy[p]){
        int mid=(l+r)/2;
        s[p*2]+=lazy[p]*(mid-l+1);
        s[p*2+1]+=lazy[p]*(r-mid);
        lazy[p*2]+=lazy[p];
        lazy[p*2+1]+=lazy[p];
        lazy[p]=0;
    }
    return;
}

void molify(int p,int l,int r,int x,int y,int v){
    if(x<=l&&y>=r){
        s[p]+=v*(r-l+1);
        lazy[p]+=v;
        return;
    }
    down(p,l,r);
    int mid=(l+r)/2;
    if(x<=mid)molify(p*2,l,mid,x,y,v);
    if(y>mid)molify(p*2+1,mid+1,r,x,y,v);
    up(p);
    return;
}

int query(int p,int l,int r,int x,int y){
    if(x<=l&&y>=r){
        return s[p];
    }
    down(p,l,r);
    int mid=(l+r)/2;
    int res=0;
    if(x<=mid)res+=query(p*2,l,mid,x,y);
    if(y>mid)res+=query(p*2+1,mid+1,r,x,y);
    return res;
}

int main(){
    int n;
    cin>>n;
    memset(s,0,sizeof(s));
    for(int i=1;i<=n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        molify(1,1,n,a,b,1);
    }
    for(int i=1;i<=n;i++){
        cout<<query(1,1,n,i,i);
        if(i!=n)cout<<" ";
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liukairui/article/details/80914284