[ODT]CF 896 C. Willem, Chtholly and Seniorious

题目描述

给出\(n\)个数,支持区间加,区间覆盖,区间第\(k\)小,区间的\(x\)次幂和.数据随机

解题思路

学ODT之前,第四个操作我是维护不来的.

第一次写ODT,ODT在数据随机有区间覆盖操作的情况下有优秀的复杂度.

关键就是用一棵平衡树维护覆盖的区间,其他就是暴力......

#include<cstdio>
#include<set>
#include<algorithm>
#define IT set<jz>::iterator
#define LL long long
using namespace std;
const int maxn=100005,tt=1e9+7;
int sd,n,m,a[maxn],vmax,top;
struct jz{
    int l,r;mutable LL v;
    jz(int l=0,int r=0,LL v=0):l(l),r(r),v(v){}
    bool operator<(const jz &b)const{return l<b.l;}
}b[maxn];
set<jz> st;
int rnd(){int num=sd;sd=((LL)sd*7+13)%tt;return num;}
IT split(int x){
    IT it=st.lower_bound(jz(x,0,0));
    if (it!=st.end()&&it->l==x) return it;it--;
    int l=it->l,r=it->r;LL v=it->v;st.erase(it);
    st.insert(jz(l,x-1,v));return st.insert(jz(x,r,v)).first;
}
void assign(int l,int r,int v){
    IT itr=split(r+1),itl=split(l);
    st.erase(itl,itr);st.insert(jz(l,r,v));
}
void add(int l,int r,int x){
    IT itr=split(r+1),itl=split(l);
    for (IT i=itl;i!=itr;i++) i->v+=x;
}
bool cmp(jz x,jz y){return x.v<y.v;}
LL kth(int l,int r,int k){
    IT itr=split(r+1),itl=split(l);top=0;
    for (IT i=itl;i!=itr;i++) b[++top]=jz(i->l,i->r,i->v);
    sort(b+1,b+1+top,cmp);
    for (int i=1;i<=top;i++) if (k<=b[i].r-b[i].l+1) return b[i].v;else k-=b[i].r-b[i].l+1;
}
int qsm(int w,int b,int tt){int num=1;while(b){if (b&1) num=(LL)num*w%tt;w=(LL)w*w%tt;b>>=1;}return num;}
int work(int l,int r,int x,int y){
    IT itr=split(r+1),itl=split(l);int num=0;
    for (IT i=itl;i!=itr;i++) num=(num+(LL)qsm(i->v%y,x,y)*(i->r-i->l+1)%y)%y;
    return num;
}
int main(){
    freopen("exam.in","r",stdin);
    freopen("exam.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&sd,&vmax);
    for (int i=1;i<=n;i++) a[i]=rnd()%vmax+1,st.insert(jz(i,i,a[i]));
    for (int i=1;i<=m;i++){
        int op=rnd()%4+1,l=rnd()%n+1,r=rnd()%n+1,x,y;
        if (l>r) swap(l,r);
        if (op==3) x=rnd()%(r-l+1)+1;else x=rnd()%vmax+1;
        if (op==4) y=rnd()%vmax+1;
        if (op==1) add(l,r,x);
        if (op==2) assign(l,r,x);
        if (op==3) printf("%lld\n",kth(l,r,x));
        if (op==4) printf("%d\n",work(l,r,x,y));
    }
    return 0;
}
上一篇:LeetCode 896——Monotonic Array


下一篇:如何使用IconFont字体图标代替网页图片?