首页 > 其他分享 >L - Intersection and Union Gym - 103993L (线段树)

L - Intersection and Union Gym - 103993L (线段树)

时间:2022-11-01 21:00:24浏览次数:59  
标签:Union Gym tr int build lmid Intersection 线段

题意

思路

思路很巧妙,首先是枚举每个值的贡献,然后找到了规律,下次做题的时候线分析每个题有啥好规律,然后根据规律做题。
再就是线段树的这个思路,感觉很巧妙,通过设置每一段的值,假设这一段出现过,那值就不是0,可以更新一次,否则,就是没出现过,值就是0。

代码

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
# define int long long
const int N=3e5+10;
const int mod=998244353;

struct node {
    int l,r;
    int maxn;
    int lazy;
}tr[N*4];
void build(int u,int l,int r){
    tr[u]={l,r,0,0};
    if(tr[u].l==tr[u].r) return;
    int mid=tr[u].l+tr[u].r>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
}
void modify(int u,int l,int r,int val){
    if(tr[u].l>=l && tr[u].r<=r){
        tr[u].maxn=val;
        return;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid) modify(u<<1,l,r,val);
    if(r>mid) modify(u<<1|1,l,r,val);
}
void query(int u,int l ,int &val){//val这里传地址,函数就不用返回最大值了
    val=max(val,tr[u].maxn);
    //如果没有包含这个l值,结果都是0,只有包含的才不是
    if(tr[u].r==tr[u].l) return ;
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid) query(u<<1,l,val);
    if(l>mid) query(u<<1|1,l,val);
}
int qmi(int a,int b){
    int ans =1;
    while(b){
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod; 
    }
    return ans;
}
signed main()
{
    build(1,0,300000);

    int n;cin>>n;
    for(int i=1;i<=n;i++){
        int l,r;
        cin>>l>>r;
        modify(1,l,r,i);
    }
        // cout<<"fs"<<endl;
    int ans=0;
    for(int i=0;i<=300000;i++){
        int val=0,sum=0;
        query(1,i,val);
        if(val==0) continue;//没有出现这个值
        if(val==1){//在第1段出现了,后面有n-1个符号
            sum=qmi(2,n-1);
        }
        else{//后面有n-val个符号,前面有3^(val-2)个集合
           sum=qmi(2,n-val+1)*qmi(3,val-2)%mod;
           sum%=mod;
        }
        ans+=sum;
        ans%=mod;
    }
    cout<<ans<<endl;
    return 0;
}

标签:Union,Gym,tr,int,build,lmid,Intersection,线段
From: https://www.cnblogs.com/kingwz/p/16849142.html

相关文章