题目描述

http://uoj.ac/problem/46

题解

看起来像是个二维平面上%*¥¥……一下,实则不然。

麻烦一点的话我们可以对时间轴开一颗线段树,在线段树上的每一个节点上再开一颗线段树表示在这个操作范围内的修改操作和。

这样我们可以修改log^2查询log^2的完成。

然而修改是区间修改,查询是单点查询,需要下传标记,数组根本开不下,UOJ上只能过2个点。

#include<iostream>
#include<cstdio>
#define N 100009
using namespace std;
typedef long long ll;
const int maxn=100000;
int ls[N*100],rs[N*100],now,ans,n,m,a[N],tott,T[N<<2];
inline int rd(){
    int x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
struct node{
    int x,y;
    node(int xx=1,int yy=0){x=xx;y=yy;}
    inline bool size(){return x!=1||y!=0;}
    inline void clear(){x=1;y=0;} 
    node operator *(const node &b)const{return node{1ll*x*b.x%m,(1ll*b.x*y%m+1ll*b.y)%m};}
}tr[N*100];
inline void pushdown(int cnt){
    if(!ls[cnt])ls[cnt]=++tott;
    if(!rs[cnt])rs[cnt]=++tott;
    tr[ls[cnt]]=tr[ls[cnt]]*tr[cnt];tr[rs[cnt]]=tr[rs[cnt]]*tr[cnt];
    tr[cnt].clear();
}
void upd2(int &cnt,int l,int r,int L,int R,int x,int y){
    if(!cnt)cnt=++tott;
    if(l>=L&&r<=R){
        tr[cnt]=tr[cnt]*node{x,y};
        return;
    }
    if(tr[cnt].size())pushdown(cnt);
    int mid=(l+r)>>1;
    if(mid>=L)upd2(ls[cnt],l,mid,L,R,x,y);
    if(mid<R)upd2(rs[cnt],mid+1,r,L,R,x,y);
}
void upd(int cnt,int l,int r,int L,int R,int x,int y){
    upd2(T[cnt],1,n,L,R,x,y);
    if(l==r)return;
    int mid=(l+r)>>1;
    if(now<=mid)upd(cnt<<1,l,mid,L,R,x,y);
    else upd(cnt<<1|1,mid+1,r,L,R,x,y);
}
void query2(int &cnt,int l,int r,int x){
    if(!cnt)return;
    if(l==r){ans=(1ll*ans*tr[cnt].x%m+1ll*tr[cnt].y)%m;return;}
    if(tr[cnt].size())pushdown(cnt);
    int mid=(l+r)>>1;
    if(mid>=x)query2(ls[cnt],l,mid,x);
    else query2(rs[cnt],mid+1,r,x);
}
void query(int cnt,int l,int r,int L,int R,int x){
    if(l>=L&&r<=R){query2(T[cnt],1,n,x);return;}
    int mid=(l+r)>>1;
    if(mid>=L)query(cnt<<1,l,mid,L,R,x);
    if(mid<R)query(cnt<<1|1,mid+1,r,L,R,x);
}
int main(){
    int id=rd();id=id&1;
    n=rd();m=rd();
    for(int i=1;i<=n;++i)a[i]=rd();
    int x,y,k,u,v;int q=rd();
    while(q--){
        int opt=rd();
        if(opt==1){
            x=rd();y=rd();u=rd();v=rd();x^=id*ans;y^=id*ans;
            now++;
            upd(1,1,maxn,x,y,u,v); 
        }
        else{
            x=rd();y=rd();k=rd();x^=id*ans;y^=id*ans;k^=id*ans;
            ans=a[k];
            query(1,1,maxn,x,y,k);
            printf("%d\n",ans);
        }
    }
    return 0;
} 
View Code

相关文章: