ODT 珂朵莉树 入门

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<set>
#define LL long long
using namespace std;
const int N = 1e5+6,mod=1e9+7;
struct node{
   int l,r;
   mutable LL v;
   node(int L,int R,LL V):l(L),r(R),v(V){}
   inline bool operator < (const node& b)const{return l<b.l;}
};
set<node>s;
int n,m;
LL a[N],seed,vmax;
inline LL Rand(){
   LL ret = seed;
   seed = (seed*7 + 13)%mod;
   return ret;
}
///快速幂
inline LL qpow(LL a,LL n,LL p){
   LL ans=1LL;a%=p;
   while(n){
      if(n&1)ans=ans*a%p;
      a=a*a%p;
      n>>=1;
   }
   return ans;
}
typedef set<node>::iterator IT;
inline IT split(int pos){ ///把pos位置的区间分成左右两节
   IT it = s.lower_bound(node(pos,pos,1));
   if(it!=s.end() && it->l==pos)return it; ///如果已经分好了 直接返回
   ///否则 我们找到这个区间的前一个区间 也就是l<pos 的区间
   --it;
   ///将这个区间给分裂成 [l,pos-1]
   ///将这个区间给分裂成 [pos,r]
   int l=it->l,r=it->r;LL v=it->v;
   s.erase(it);
   s.insert(node(l,pos-1,v));
   return s.insert(node(pos,r,v)).first;
}
///暴力区间加 直接把这个区间内的数全部+V
inline void add(int l,int r,LL v){
   IT it1 = split(l),it2=split(r+1);
   for(;it1!=it2;++it1)it1->v+=v;
}
///区间赋值
inline void assigns(int l,int r,LL v){
   ///把区间断成[1-l-1] [l,r] [r+1,n]
   IT it1 = split(l),it2=split(r+1);
   ///清除[l,r]的多余的区间
   s.erase(it1,it2);
   ///加入新赋值的区间
   s.insert(node(l,r,v));
}
///区间第K大
inline void Rank(int l,int r,int k){
   IT it1=split(l),it2=split(r+1);
   vector<pair<LL,int> >t;
   for (;it1!=it2;++it1)t.push_back(pair<LL,int>(it1->v,it1->r - it1->l +1));
   sort(t.begin(),t.end());
   LL ans=0;
   for (auto it : t){  ///便利类似容器的begin 到 end 可以直接用auto 
      if (k<=it.second){
         ans=it.first;
         break;
      }else {
         k-=it.second;
      }
   }
   printf("%lld\n",ans);
}
inline void sum(int l,int r,int x,int p){
   IT it1=split(l),it2=split(r+1);
   LL ans=0;
   for(;it1!=it2;++it1)ans=(ans+(LL)(it1->r - it1->l+1)*qpow(it1->v,x,p))%p;
   printf("%lld\n",ans);
}
int main(){
   scanf("%d%d%lld%lld",&n,&m,&seed,&vmax);
   for(int i=1;i<=n;i++){
     a[i]=Rand()%vmax+1;
     s.insert(node(i,i,a[i]));
   }
   s.insert(node(n+1,n+1,0));
   for(int i=1;i<=m;i++){
      int opt=Rand()%4+1;
      int l=Rand()%n+1;
      int r=Rand()%n+1;
      if(l>r)swap(l,r);
      int x=0,y=0;
      if(opt==3)x=Rand()%(r-l+1)+1;
      else x=Rand()%vmax+1;
      if(opt==4)y=Rand()%vmax+1;
      if(opt==1)add(l,r,x);
      else if (opt==2)assigns(l,r,x);
      else if (opt==3)Rank(l,r,x);
      else sum(l,r,x,y);
   }
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/bluefly-hrbust/p/11494097.html
ODT