题解 P5893 【[IOI2013]game 游戏】

· · 题解

题目大意

二维单点修改区间求\gcd题目描述得已经很清楚了吧qwq

题解

这种二维问题大概什么树套树都能过,我这里用的是线段树套线段树,以下是一些需要注意的细节:

时空效率O(Nlog^2N)(这里认为N,N_U,N_Q同级)

以下代码:

#include<cstdio>
#include<algorithm>
#define ll long long
#define NU 22005
#define NQ 250005

inline void rd(int &x){
    x=0;
    char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';
        c=getchar();
    }
}
inline void rdll(ll &x){
    x=0;
    char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    while(c>='0'&&c<='9'){
        x=x*10+c-'0';
        c=getchar();
    }
}

int n;
struct query{
    int opt,x1,y1,x2,y2;
    ll val;
}qry[NU+NQ];

int Valu[NU],_Valu,Valq[NU+(NQ<<1)],_Valq;
inline void unq(){
    std::sort(Valu+1,Valu+_Valu+1);
    _Valu=std::unique(Valu+1,Valu+_Valu+1)-Valu-1;
    std::sort(Valq+1,Valq+_Valq+1);
    _Valq=std::unique(Valq+1,Valq+_Valq+1)-Valq-1;
}
inline int idu(int val){
    return std::upper_bound(Valu+1,Valu+_Valu+1,val)-Valu-1;
}
inline int idq(int val){
    return std::upper_bound(Valq+1,Valq+_Valq+1,val)-Valq-1;
}

inline ll gcd(ll x,ll y){
    while(x&&y){
        ll tmp=x%y;
        x=y;
        y=tmp;
    }
    return x+y;
}

int _t;
struct node{
    int son[2];
    ll val;
}t[NU<<9];
#define lson t[p].son[0],L,mid
#define rson t[p].son[1],mid+1,R
inline void ins(int &p,int L,int R,int pos,ll val){
    if(!p)
        p=++_t;
    if(L==R){
        t[p].val=val;
        return;
    }
    int mid=(L+R)>>1;
    if(pos<=mid)
        ins(lson,pos,val);
    else
        ins(rson,pos,val);
    t[p].val=gcd(t[t[p].son[0]].val,t[t[p].son[1]].val);
}
inline void mrg(int &p,int L,int R,int q1,int q2,int pos){
    if(!p)
        p=++_t;
    if(L==R){
        t[p].val=gcd(t[q1].val,t[q2].val);
        return;
    }
    int mid=(L+R)>>1;
    if(pos<=mid)
        mrg(lson,t[q1].son[0],t[q2].son[0],pos);
    else
        mrg(rson,t[q1].son[1],t[q2].son[1],pos);
    t[p].val=gcd(t[t[p].son[0]].val,t[t[p].son[1]].val);
}
inline ll Cal(int p,int L,int R,int l,int r){
    if(!p||Valu[L]>r||Valu[R]<l)
        return 0;
    if(l<=Valu[L]&&Valu[R]<=r)
        return t[p].val;
    int mid=(L+R)>>1;
    return gcd(Cal(lson,l,r),Cal(rson,l,r));
}
#undef lson
#undef rson

int rt[(NU+(NQ<<1))<<2];
#define lson p<<1,L,mid
#define rson p<<1|1,mid+1,R
inline void mdf(int p,int L,int R,int pos,int pos2,ll val){
    if(pos<L||pos>R)
        return;
    if(L==R){
        ins(rt[p],1,_Valu,pos2,val);
        return;
    }
    int mid=(L+R)>>1;
    mdf(lson,pos,pos2,val);
    mdf(rson,pos,pos2,val);
    mrg(rt[p],1,_Valu,rt[p<<1],rt[p<<1|1],pos2);
}
inline ll cal(int p,int L,int R,int l,int r,int l2,int r2){
    if(L>r||R<l)
        return 0;
    if(l<=L&&R<=r)
        return Cal(rt[p],1,_Valu,l2,r2);
    int mid=(L+R)>>1;
    return gcd(cal(lson,l,r,l2,r2),cal(rson,l,r,l2,r2));
}
#undef lson
#undef rson

int main(){
    rd(n),rd(n),rd(n);
    for(int i=1;i<=n;i++){
        rd(qry[i].opt);
        if(qry[i].opt==1){
            rd(qry[i].x1),rd(qry[i].y1),rdll(qry[i].val);
            Valu[++_Valu]=qry[i].y1;
            Valq[++_Valq]=qry[i].x1;
        }
        else{
            rd(qry[i].x1),rd(qry[i].y1),rd(qry[i].x2),rd(qry[i].y2);
            Valq[++_Valq]=qry[i].x1;
            Valq[++_Valq]=qry[i].x2;
        }
    }
    unq();
    for(int i=1;i<=n;i++)
        if(qry[i].opt==1)
            mdf(1,1,_Valq,idq(qry[i].x1),idu(qry[i].y1),qry[i].val);
        else
            printf("%lld\n",cal(1,1,_Valq,idq(qry[i].x1),idq(qry[i].x2),qry[i].y1,qry[i].y2));

  #define w 0
  return ~~('0')?(0^w^0):(0*w*0);
}