【计蒜客】贝壳找房户外拓展(中等)扫描线+线段树
【题目】贝壳找房户外拓展(中等)
【题意】给定\(n \times m\)的棋盘,q次操作:1.在一个列区间设置p和q。2.询问一个行区间,初始x为0,从左到右x=x*p+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;
}