UOJ#46. 清华集训2014玄学

Posted yzxverygood

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UOJ#46. 清华集训2014玄学相关的知识,希望对你有一定的参考价值。

传送门

分析

清华集训真的不是人做的啊嘤嘤嘤

我们可以考虑按操作时间把每个操作存进线段树里

如果现在点x正好使一个整块区间的右端点则更新代表这个区间的点

我们不难发现一个区间会因为不同的操作被分成若干块,每块对应序列上不同的区间

于是查询时对于每个线段树上区间查询时二分查找当前点在哪一块中即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
int n,m,a[100100],Q,tot,Ans,cnt,L[3001000],R[3001000];
struct node {
    int le,ri,a,b;
};
node d[30010000];
inline void PUSH(int wh,int le,int ri,int aa,int bb){
    d[wh].le=le,d[wh].ri=ri,d[wh].a=aa,d[wh].b=bb;
}
inline void update(int wh,int le,int ri){
    int i,j,k,be=1;
    L[wh]=cnt+1;
    for(i=L[le],j=L[ri];i<=R[le]&&j<=R[ri];){
      if(d[i].ri>=d[j].ri){
          PUSH(++cnt,be,d[j].ri,d[i].a*d[j].a%m,(d[j].a*d[i].b+d[j].b)%m);
          be=d[j].ri+1;
          if(d[i].ri==d[j].ri)i++;
          j++;
      }else {
          PUSH(++cnt,be,d[i].ri,d[i].a*d[j].a%m,(d[j].a*d[i].b%m+d[j].b)%m);
          be=d[i].ri+1;
          i++;
      }
    }
    R[wh]=cnt;
}
inline void build(int le,int ri,int wh,int pl,int x,int y,int k1,int k2){
    if(le==ri){
      L[wh]=cnt+1;
      if(x>1)PUSH(++cnt,1,x-1,1,0);
      PUSH(++cnt,x,y,k1,k2);
      if(y<n)PUSH(++cnt,y+1,n,1,0);
      R[wh]=cnt;
      return;
    }
    int mid=(le+ri)>>1;
    if(mid>=pl)build(le,mid,wh<<1,pl,x,y,k1,k2);
      else build(mid+1,ri,wh<<1|1,pl,x,y,k1,k2);
    if(ri==pl)update(wh,wh<<1,wh<<1|1);
}
inline void work(int wh,int pl){
    int le=L[wh],ri=R[wh];
    while(ri-le>0){
      int mid=(le+ri)>>1;
      if(pl<=d[mid].ri)ri=mid; 
        else le=mid+1;
    }
    Ans=(Ans*d[le].a%m+d[le].b)%m;
}
inline void q(int le,int ri,int wh,int x,int y,int k){
    if(le>=x&&ri<=y){
      work(wh,k);
      return;
    }
    int mid=(le+ri)>>1;
    if(mid>=x)q(le,mid,wh<<1,x,y,k);
    if(mid<y)q(mid+1,ri,wh<<1|1,x,y,k);
}
signed main(){
    int i,j,k,t;
    scanf("%lld",&t);
    scanf("%lld%lld",&n,&m);
    for(i=1;i<=n;i++)scanf("%lld",&a[i]);
    scanf("%lld",&Q);
    for(i=1;i<=Q;i++){
      int le,ri,x,y;
      scanf("%lld%lld%lld",&k,&le,&ri);
      if(t&1)le^=Ans,ri^=Ans;
      if(k==1){
          scanf("%lld%lld",&x,&y);
          tot++;
          build(1,Q,1,tot,le,ri,x,y);
      }else {
          scanf("%lld",&x);
          if(t&1)x^=Ans;
          Ans=a[x];
          q(1,Q,1,le,ri,x);
          printf("%lld
",Ans);
      }
    }
    return 0;
}

以上是关于UOJ#46. 清华集训2014玄学的主要内容,如果未能解决你的问题,请参考以下文章

UOJ #46 清华集训2014玄学

uoj #46[清华集训2014]玄学

[UOJ46][清华集训2014]玄学

UOJ46. 清华集训2014玄学

#46. 清华集训2014玄学

AC日记——清华集训2014奇数国 uoj 38