[FJOI2015]火星商店问题

description

题面

solution

跟着各位dalao写了一下线段树分治的题

我们把修改和询问按照时间建立线段树分治,
对于每一个修改标记永久化,对于每一个区间进行区间覆盖

主要的想法就是对每一个线段树节点开一个\(vector\)记录所有的修改和询问
在线段树上的一条链上插入修改,使用区间覆盖的方法在线段树上插入询问
对整棵线段树进行\(dfs\),每次取出节点上的\(vector\)并对其进行处理
大概就是这样

void segdiv(int i,int l,int r){//线段树分治???
    work(f[i],g[i]);if(l==r)return;segdiv(ls,l,mid);segdiv(rs,mid+1,r);
}

il void insertmodify(int i,int l,int r,int x,int y,modify mdf){
    //这里是插入修改
    f[i].push_back(mdf);
    if(l==r)return;
    if(x<=mid)insertmodify(ls,l,mid,x,y,mdf);
    else insertmodify(rs,mid+1,r,x,y,mdf);
}
il void insertquery(int i,int l,int r,int x,int y,ask q){
    //这里是插入询问
    if(y<x)return;
    if(x<=l&&r<=y){g[i].push_back(q);return;}
    if(x<=mid)insertquery(ls,l,mid,x,y,q);
    if(mid<y)insertquery(rs,mid+1,r,x,y,q);
}

code

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define FILE "a"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=1e5+10;
const int T=5e6+10;
const dd pi=acos(-1);
const int inf=2147483647;
const ll INF=1e18+1;
il ll read(){
    RG ll data=0,w=1;RG char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    return data*w;
}
il void file(){
    srand(time(NULL)+rand());
    freopen(FILE".in","r",stdin);
    freopen(FILE".out","w",stdout);
}

struct modify{int a,b,day;}M[N];
bool cmp(modify x,modify y){return x.a<y.a;}
struct ask{int id,a,b,c,d,e;}Q[N];
int n,m,day,mt,qt,ans[N],pw[21],tot,num[N],sz;
vector<modify>f[N<<5];
vector<ask>g[N<<5];
int rt[N],s[N<<5][2],sum[N<<5];
il void insert(int cur,int lst,int val){
    sum[cur]=sum[lst]+1;bool d;
    for(RG int i=17;~i;i--){
        d=val&pw[i];
        s[cur][d]=++tot;s[cur][!d]=s[lst][!d];
        sum[s[cur][d]]=sum[s[lst][d]]+1;
        cur=s[cur][d];lst=s[lst][d];
    }
}
il int query(int l,int r,int x){
    if(l>r)return 0;
    l=rt[l-1];r=rt[r];bool d;int ret=0;
    for(RG int i=17;~i;i--){
        d=x&pw[i];
        if(sum[s[r][!d]]-sum[s[l][!d]]>0){
            ret|=pw[i];r=s[r][!d];l=s[l][!d];
        }
        else{r=s[r][d];l=s[l][d];}
    }
    return ret;
}
void work(vector<modify>F,vector<ask>G){
    RG int ft=F.size(),gt=G.size();
    tot=sz=0;
    for(RG int i=0;i<ft;i++){
        num[++sz]=F[i].a;
        insert(rt[i+1]=++tot,rt[i],F[i].b);
    }
    for(RG int i=0,l,r;i<gt;i++){
        l=lower_bound(num+1,num+sz+1,G[i].a)-num;
        r=upper_bound(num+1,num+sz+1,G[i].b)-num-1;
        ans[G[i].id]=max(ans[G[i].id],query(l,r,G[i].e));
    }
}

#define ls (i<<1)
#define rs (i<<1|1)
#define mid ((l+r)>>1)
il void insertmodify(int i,int l,int r,int x,int y,modify mdf){
    f[i].push_back(mdf);
    if(l==r)return;
    if(x<=mid)insertmodify(ls,l,mid,x,y,mdf);
    else insertmodify(rs,mid+1,r,x,y,mdf);
}
il void insertquery(int i,int l,int r,int x,int y,ask q){
    if(y<x)return;
    if(x<=l&&r<=y){g[i].push_back(q);return;}
    if(x<=mid)insertquery(ls,l,mid,x,y,q);
    if(mid<y)insertquery(rs,mid+1,r,x,y,q);
}
void segdiv(int i,int l,int r){
    work(f[i],g[i]);if(l==r)return;segdiv(ls,l,mid);segdiv(rs,mid+1,r);
}

int main()
{
    n=read();m=read();pw[0]=1;for(RG int i=1;i<=20;i++)pw[i]=pw[i-1]<<1;
    for(RG int i=1;i<=n;i++)insert(rt[i]=++tot,rt[i-1],read());
    for(RG int i=1,o,a,b,c,d;i<=m;i++){
        o=read();
        if(!o){day++;a=read();b=read();M[++mt]=(modify){a,b,day};}
        else{
            a=read();b=read();d=read();c=read();
            Q[++qt]=(ask){qt,a,b,max(day-c,0)+1,day,d};
        }
    }
    for(RG int i=1;i<=qt;i++)
        ans[i]=max(ans[i],query(Q[i].a,Q[i].b,Q[i].e));
    sort(M+1,M+mt+1,cmp);   
    for(RG int i=1;i<=mt;i++)insertmodify(1,1,day,M[i].day,day,M[i]);
    for(RG int i=1;i<=qt;i++)
        if(Q[i].d)insertquery(1,1,day,max(Q[i].c,1),Q[i].d,Q[i]);
    segdiv(1,1,day);    
    for(RG int i=1;i<=qt;i++)printf("%d\n",ans[i]);return 0;
}

猜你喜欢

转载自www.cnblogs.com/cjfdf/p/9379550.html