CF896C Willem, Chtholly and Seniorious

题目链接

CF896C Willem, Chtholly and Seniorious

【题面】
请你写一种奇怪的数据结构,支持:

  • 1 l r x :将[l,r] 区间所有数加上x
  • 2 l r x :将[l,r] 区间所有数改成x
  • 3 l r x :输出将[l,r] 区间从小到大排序后的第x 个数是的多少(即区间第x 小,数字大小相同算多次,保证 1 x rl+1 )
  • 4 l r x y :输出[l,r] 区间每个数字的x 次方的和模y 的值(即(i=lraix ) mody )

【输入格式】
这道题目的输入格式比较特殊,需要选手通过seed 自己生成输入数据。
输入一行四个整数n,m,seed,vmax1 n,m105 ,0seed109+7 ,1vmax109
其中n 表示数列长度,m 表示操作次数,后面两个用于生成输入数据。
数据生成的伪代码如下

def rnd(): ret = seed seed = (seed * 7 + 13) mod 1000000007 return ret for i = 1 to n: a[i] = (rnd() mod vmax) + 1 for i = 1 to m: op = (rnd() mod 4) + 1 l = (rnd() mod n) + 1 r = (rnd() mod n) + 1 if (l > r): swap(l, r) if (op == 3): x = (rnd() mod (r - l + 1)) + 1 else: x = (rnd() mod vmax) + 1 if (op == 4): y = (rnd() mod vmax) + 1

其中上面的op指题面中提到的四个操作。

【输出格式】
对于每个操作3和4,输出一行仅一个数。

解题思路

珂朵莉树

珂朵莉树是一种优雅的暴力,常用来解决数据随机且带有区间赋值操作的问题

核心思想在于将值相等的区间合并为一个节点保存在 set 中,同时还有一个关键函数 split(x),表示将含有 x 的区间 [l,r] 分为 [l,x1],[x,r] 两个区间,同时返回后者,所以对于区间 [l,r],可以分为 [split(l),split(r+1)) 这些 set 上的节点,其他操作据此暴力计算或修改即可
注意分区间的时候先 split(r+1) 然后 split(l)

  • 时间复杂度:O(mlog2n)

代码

// Problem: C. Willem, Chtholly and Seniorious // Contest: Codeforces - Codeforces Round #449 (Div. 1) // URL: https://codeforces.com/contest/896/problem/C // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> // #define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int mod=1e9+7; int n,m,seed,vmax; struct odt { int l,r; mutable LL v; odt(const int &_l,const int &_r,const LL &_v):l(_l),r(_r),v(_v){} inline bool operator<(const odt &o)const { return l<o.l; } }; set<odt> s; int rnd() { int res=seed; seed=(1ll*seed*7+13)%mod; return res; } auto split(int x) { auto it=--s.upper_bound({x,0,0}); if(it->l==x)return it; int l=it->l,r=it->r; LL v=it->v; s.erase(it); s.insert({l,x-1,v}); return s.insert({x,r,v}).fi; } void add(int l,int r,int x) { auto itr=split(r+1),itl=split(l); while(itl!=itr)itl->v+=x,itl++; } void assign(int l,int r,int v) { auto itr=split(r+1),itl=split(l); s.erase(itl,itr); s.insert({l,r,v}); } LL ask_kth(int l,int r,int k) { auto itr=split(r+1),itl=split(l); vector<pair<LL,int>> a; while(itl!=itr) { a.pb({itl->v,itl->r-itl->l+1}); itl++; } sort(a.begin(),a.end()); for(auto t:a) { k-=t.se; if(k<=0)return t.fi; } return -1; } int ksm(LL a,int b,int p) { int res=1%p; a%=p; while(b) { if(b&1)res=1ll*res*a%p; a=1ll*a*a%p; b>>=1; } return res; } int ask_sum(int l,int r,int x,int y) { auto itr=split(r+1),itl=split(l); int res=0; while(itl!=itr) { res=(1ll*res+1ll*ksm(itl->v,x,y)*(itl->r-itl->l+1))%y; itl++; } return res; } int main() { scanf("%d%d%d%d",&n,&m,&seed,&vmax); for(int i=1;i<=n;i++)s.insert({i,i,rnd()%vmax+1}); while(m--) { int op=rnd()%4+1; int l=rnd()%n+1,r=rnd()%n+1; if(l>r)swap(l,r); int x,y; 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); else if(op==2)assign(l,r,x); else if(op==3) printf("%lld\n",ask_kth(l,r,x)); else printf("%d\n",ask_sum(l,r,x,y)); } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16807248.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示