求助两道线段树题,悬两关
  • 板块灌水区
  • 楼主__2304__
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/10/13 09:32
  • 上次更新2024/10/13 11:50:56
查看原帖
求助两道线段树题,悬两关
719611
__2304__楼主2024/10/13 09:32

1

用线段树维护的差分序列,每次修改l加上首项,r+1减去末项,l+1到r加公差,91pts

2(P1558)

cnt中,每种颜色对应到一个位上,然后更新大区间的时候就把两个子区间按位或一下,最后数1的个数就能数出有多少种颜色,但是为什么只过了subtask1(((

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXL=1e5+5;
struct SegmentTree{
    ll l,r,cnt,tag;
    #define l(x) T[x].l
    #define r(x) T[x].r
    #define cnt(x) T[x].cnt
    #define tag(x) T[x].tag
}T[MAXL*4];
ll l,t,o;
ll countone(ll p){
    ll cnt=0;
    while(p){
        if(p%2==1) cnt++;
        p/=2;
    }
    return cnt;
}
void build(ll p,ll l,ll r){
    l(p)=l,r(p)=r;
    if(l==r){cnt(p)=1;return;}
    ll mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    cnt(p)=cnt(p*2)|cnt(p*2+1);
}
void spread(ll p){
    if(tag(p)){
        cnt(p*2)=tag(p);
        cnt(p*2+1)=tag(p);
        tag(p*2)=tag(p);
        tag(p*2+1)=tag(p);
        tag(p)=0;
    }
}
void change(ll p,ll l,ll r,ll d){
    if(l<=l(p)&&r>=r(p)){
        cnt(p)=1<<(d-1);
        tag(p)=1<<(d-1);
        return;
    }
    spread(p);
    ll mid=(l(p)+r(p))/2;
    if(l<=mid) change(p*2,l,r,d);
    if(r>mid) change(p*2+1,l,r,d);
    cnt(p)=cnt(p*2)|cnt(p*2+1);
}
ll ask(ll p,ll l,ll r){
    if(l<=l(p)&&r>=r(p)) return cnt(p);
    spread(p);
    ll mid=(l(p)+r(p))/2,val=0;
    if(l<=mid) val|=ask(p*2,l,r);
    if(r>mid) val|=ask(p*2+1,l,r);
    return val;
}
int main(){
    cin>>l>>t>>o;
    build(1,1,l);
    for(int i=1;i<=o;i++){
        char opt;
        cin>>opt;
        if(opt=='C'){
            int a,b,c;
            cin>>a>>b>>c;
            change(1,a,b,c);
        }
        else if(opt=='P'){
            int a,b;
            cin>>a>>b;
            cout<<countone(ask(1,a,b))<<endl;
        }
    }
    return 0;
}
2024/10/13 09:32
加载中...