【CF896C】Willem, Chtholly and Seniorious

ODT模板题,ODT适合随机数据下具有维护区间推平操作的序列维护题目,时间复杂度较为玄学。。

代码如下

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
using namespace std;
const int maxn=1e5+10;
const int mod=1e9+7;
typedef long long LL;
LL fpow(LL a,LL b,LL c){
    LL ret=1%c;
    for(;b;b>>=1,a=a*a%c)if(b&1)ret=ret*a%c;
    return ret;
}

int n,m;
LL seed,vmax;
LL rnd(){
    LL ret=seed;
    seed=(seed*7+13)%mod;
    return ret;
}
struct node{
    int l,r;
    mutable LL val;
    node(int x=0,int y=0,LL z=0):l(x),r(y),val(z){}
    bool operator<(const node &rhs)const{
        return this->l<rhs.l;
    }
};
set<node> s;
auto split(int pos){
    auto it=s.lower_bound(node(pos));
    if(it!=s.end()&&it->l==pos)return it;
    --it;
    int l=it->l,r=it->r;
    LL val=it->val;
    s.erase(it);
    s.insert(node(l,pos-1,val));
    return s.insert(node(pos,r,val)).first;
}
void add(int l,int r,LL x){
    auto itr=split(r+1),itl=split(l);
    for(auto it=itl;it!=itr;it++)it->val+=x;
}
void assign(int l,int r,LL x){
    auto itr=split(r+1),itl=split(l);
    s.erase(itl,itr);
    s.insert(node(l,r,x));
}
LL kth(int l,int r,int k){
    auto itr=split(r+1),itl=split(l);
    vector<pair<LL,int>> v;v.clear();
    for(auto it=itl;it!=itr;it++){
        v.pb(mp(it->val,it->r-it->l+1));
    }
    sort(all(v));
    for(auto p:v){
        k-=p.second;
        if(k<=0)return p.first; 
    }
    return -1;
}
LL sum(int l,int r,int x,int y){
    auto itr=split(r+1),itl=split(l);
    LL ret=0;
    for(auto it=itl;it!=itr;it++){
        ret=(ret+fpow(it->val%y,x,y)*(it->r-it->l+1)%y)%y;
    }
    return ret;
}

int main(){
    scanf("%d%d%lld%lld",&n,&m,&seed,&vmax);
    for(int i=1;i<=n;i++){
        s.insert(node(i,i,rnd()%vmax+1));
    }
    s.insert(node(n+1,n+1,0));
    
    while(m--){
        int opt=rnd()%4+1,l=rnd()%n+1,r=rnd()%n+1,x,y;
        if(l>r)swap(l,r);
        if(opt==3)x=rnd()%(r-l+1)+1;
        else x=rnd()%vmax+1;
        if(opt==4)y=rnd()%vmax+1;
        if(opt==1)add(l,r,x);
        else if(opt==2)assign(l,r,x);
        else if(opt==3)printf("%lld\n",kth(l,r,x));
        else if(opt==4)printf("%lld\n",sum(l,r,x,y));
    }
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wzj-xhjbk/p/10955441.html