【计蒜客】贝壳找房户外拓展(中等)扫描线+线段树

【题目】贝壳找房户外拓展(中等)
【题意】给定nm的棋盘,q次操作:1.在一个列区间设置p和q。2.询问一个行区间,初始x为0,从左到右x=xp+q,求x。3.撤销一次设置操作。保证所有1和3都在2前面。\(n,m,q \leq 10^5\)
【算法】扫描线+线段树
【题解】离线x维进行扫描线,每次列区间的设置在上端+1,下端+1处-1,这样就转化为序列上的单点插入和区间查询。
考虑线段树维护两个值P和Q,每次合并\(P=P_1*P_2,Q=Q_1*P_2+Q_2\)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
#define ll long long
#define lowbit(x) x&-x
using namespace std;
bool isdigit(char c){return c>='0'&&c<='9';}
int read(){
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c=='-')t=-1;
    do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    return s*t;
}
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a<b?b:a;}
int ab(int x){return x>0?x:-x;}
//int MO(int x){return x>=MOD?x-MOD:x;}
//void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
/*------------------------------------------------------------*/
const int inf=0x3f3f3f3f,MOD=323232323,maxn=100010;

int n,m,tot=0,cnt=0,ANS[maxn];
bool vis[maxn];
char s[10];
struct A{
    int x,l,r,id;
    bool operator < (const A &a)const{
        return x<a.x;
    }
}a[maxn];
struct B{
    int x,y,p,q,kind;
    bool operator < (const B &a)const{
        return x<a.x;
    }
}b[maxn*2];
struct tree{int l,r,p,q;}t[maxn*4];
void up(int k){
    t[k].p=1ll*t[k<<1].p*t[k<<1|1].p%MOD;
    t[k].q=(1ll*t[k<<1].q*t[k<<1|1].p+t[k<<1|1].q)%MOD;
}
void build(int k,int l,int r){
    t[k].l=l;t[k].r=r;t[k].p=1;t[k].q=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}
void insert(int k,int x,int p,int q){
    if(t[k].l==t[k].r){t[k].p=p;t[k].q=q;return;}
    int mid=(t[k].l+t[k].r)>>1;
    if(x<=mid)insert(k<<1,x,p,q);
    else insert(k<<1|1,x,p,q);
    up(k);
}
int P,Q;
void query(int k,int l,int r){
    if(l<=t[k].l&&t[k].r<=r){P=1ll*P*t[k].p%MOD;Q=(1ll*Q*t[k].p+t[k].q)%MOD;return;}
    int mid=(t[k].l+t[k].r)>>1;
    if(l<=mid)query(k<<1,l,r);
    if(r>mid)query(k<<1|1,l,r);
}   
int main(){
    n=read();m=read();int T=read();
    memset(vis,0,sizeof(vis));
    int kind=0;
    while(T--){//chong ming
        scanf("%s",s);
        if(s[0]=='I'){
            kind++;
            int l=read(),r=read(),y=read(),p=read(),q=read();
            b[++tot]=(B){l,y,p,q,kind};
            b[++tot]=(B){r+1,y,1,0,kind};
        }
        else if(s[0]=='D'){
            int k=read();
            vis[k]=1;
        }
        else{
            cnt++;a[cnt].x=read();a[cnt].l=read();a[cnt].r=read();a[cnt].id=cnt;
        }
    }
    sort(b+1,b+tot+1);sort(a+1,a+cnt+1);
    int x=0;
    build(1,1,m);
    for(int i=1;i<=cnt;i++){
        while(x+1<=tot&&b[x+1].x<=a[i].x){x++;if(!vis[b[x].kind])insert(1,b[x].y,b[x].p,b[x].q);}//if bu duan while
        P=1;Q=0;query(1,a[i].l,a[i].r);
        ANS[a[i].id]=Q;
    }
    for(int i=1;i<=cnt;i++)printf("%d\n",ANS[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/onioncyc/p/9064871.html
今日推荐