2025省选模拟5

 


2025省选模拟5

T1、 枇杷树

题意是说每次会使用前面的两棵树通过每棵树各一个点之间连了一条边然后组成一颗新树,我们可以从这个性质入手。

对于每次 ans 的计算 , 我们把贡献分开来看,对于一棵树,我们把它分成组成他的两棵树 x,y ,那么所有点对距离之和可以分为 x 子树里的点对之和 和 y 子树里的点对之和 和 x 里的点与 y 里的点两两匹配的 dis 和。

于是答案可以分成子问题去算:

ansi=ansx+ansy+fx,u×szy+fy,v×szx+w×szx×szy

其中 fx,y 表示 i=0szx1dis(i,y)

然后问题转化成了求解 fx,y ,我们考虑继续去把 x 树分开,然后递归计算。假设对于 fi,jii1,i2 两棵树通过 u,v 连接组成,其中 ji1 里,那么有

fi,j=fi1,j+fi2,v+(w+disx,u,j)×szi2

然后我们发现又多出来了一个 disx,u,j ,他表示在 x 树内 u,j 两点间的距离 ,我们继续对他拆分,分讨两个点在不在同一颗子树内即可。

这样显然会 T ,那我们最多也就是上个记忆化对吧,但是上了记忆化你会发现不 T 了,那我们分析一下复杂度:首先我们称每次连边的 u,v关键点 , 那么 f 只有 O(m2) 种状态 , 那对于 dis 他也只会有 O(m3) 种状态,因为后两维都一定是关键点,而第一维显然最多也是 O(m) 的,所以记忆化之后时间复杂度就是 O(m3) 的。

T2、 上古遗迹

首先如果是全局查询的话,这就是很简单的单调栈就做完了,但对于询问的不是全局而是区间 [l,r] ,我们会发现 [l,r] 和一个点 i 的合法区间左边界 Li,和右边界 Ri 的大小关系不同时,这个点的贡献不同,那就比较麻烦了,我们直接分讨。

case 1

对于 lLRr 的情况,这个点的贡献是定的,也就是 (RiLi+1)×hi 直接扫描线加树状数组即可。

case 2

对于 LlrR 的情况,点 i 的贡献为 (rl+1)×hi ,和上一个一样,同样扫描线加树状数组即可。

case 3

对于 lLrR 的情况,点 i 的贡献是 (rL+1)×hi=r×hi+(1L)×hi ,这是一个一次函数的形式,其中 r 为横坐标, hi 为斜率,我们注意到求值的横坐标 r 需要受到 LrR 的限制,可以转化为李超线段树插入线段,再加上一个扫描线即可。

case 4

对于 LlRr 的情况,与 case3 相同。

时间复杂度为 O(nlog2n) ,瓶颈是李超线段树插入线段。

T3、 吞天得手

看上去好像很简单,但又不想写。

首先考虑我们已经目前一个最优的前缀,比起改变它里面的某个数,一定不如往他后面加入一个数更优,所以思路就是,我们一开始有一个最优前缀 S(初始为空集),然后我们以此找到他后面的第一小的数加在 S 后面形成 T ,然后输出他并使它作为新的最优前缀,然后这个新的前缀 T 仿照之前的做法继续走,直到无法继续走,然后你就只能回来 S 这,然后去找他后面第二小的数,然后再回来,然后找第 3,4,5,...... , k 小的数,这个过程可以直接使用递归实现,但是你发现再有同样的数的情况下他就错了,因为第 1 、2小的数可能相同,但上面的做法是先找到第一小的数然后将其作为新前缀去递归,这样就不对了。所以我们每次要把相同的数都找出来,将它们一起处理。

一个好写的做法就是在 dfs 中存一个优先队列 q ,队列里放结构体 i=(pos,k,ans,zhp) 分别表示 前缀 i 是位置 pos 接上他后面的第 k 小的数,他的位置是 zhp ,这个前缀的哈希值(输出方案)是 ans ,然后每次取出堆顶,将其接上 zhp 后面的第 1 小的数放进一个新优先队列 qq 里,然后将 i 改为 i 去除 zhp 上的数,并加上 pos 后第 k+1 小的数,并作出相应修改,然后放回队列里。每次取堆顶直到队列空了或者两者的实际代表前缀不一样,然后将所有取出来的前缀输出,并 dfs 到下一层,将 qq 作为他的初始队列。

讲的可能比较乱,看一下代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define fi first
#define se second
#define ps push_back
#define mk make_pair
const int N=1e6+10,inf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f,mod=998244353;
inline ll read(){
char c=getchar();ll x=0;bool f=0;
while(!isdigit(c))f=c=='-'?1:0,c=getchar();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f?-x:x;
}
int n,K,b,a[N],rt[N];
int cnt[N<<3],son[N<<3][2],tot;
inline void add(int &k,int l,int r,int pos){
cnt[++tot]=cnt[k]+1,son[tot][0]=son[k][0],son[tot][1]=son[k][1];
k=tot;
if(l==r)return;
int mid=l+r>>1;
pos<=mid?add(son[k][0],l,mid,pos):add(son[k][1],mid+1,r,pos);
}
inline pii ask(int k,int v){
int l=1,r=1e5,mid;
while(l<r){
mid=l+r>>1;
if(v<=cnt[son[k][0]])k=son[k][0],r=mid;
else v-=cnt[son[k][0]],l=mid+1,k=son[k][1];
}
return {l,v};
}
struct jj{
int pos,ans,k,zhp;
inline bool operator <(const jj&x)const{return a[zhp]>a[x.zhp];}
};
vector<int> v[N>>3];// v[i] 存放了 a[pos] = i 的所有位置,以便查找 zhp
inline void dfs(priority_queue<jj> q){
while(q.size()){
auto k=q.top();
priority_queue<jj> qq;
while(q.size()&&q.top().ans==k.ans){
auto i=q.top();q.pop();--K;
cout<<i.ans<<'\n';
if(K<=0)exit(0);
jj j=i;
j.pos=i.zhp;j.k=1;
if(j.k+j.pos<=n){
auto tp=ask(rt[j.pos+1],j.k);// ask 为主席树查询第 k 大,返回 pair<int,int> 类型,first 表示第 k 大的值,second表示第 k 大在相同值中是第几个,为了查询 zhp
j.ans=(i.ans*b+tp.fi)%mod;j.zhp=v[tp.fi][upper_bound(v[tp.fi].begin(), v[tp.fi].end(),j.pos)-v[tp.fi].begin()+tp.se-1];
qq.push(j);
}
i.k++;if(i.k+i.pos>n)continue;
i.ans=(i.ans-a[i.zhp])%mod;
auto tp=ask(rt[i.pos+1],i.k);
i.ans=(i.ans+tp.fi)%mod;i.zhp=v[tp.fi][upper_bound(v[tp.fi].begin(), v[tp.fi].end(),i.pos)-v[tp.fi].begin()+tp.se-1];
q.push(i);
}
dfs(qq);
}
}
signed main(){
// #ifndef ONLINE_JUDGE
freopen("ttds.in","r",stdin);
freopen("ttds.out","w",stdout);
// #endif
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
n=read(),K=read(),b=read();
for(int i=1;i<=n;++i)
a[i]=read(),v[a[i]].ps(i);
for(int i=n;i;--i)
rt[i]=rt[i+1],add(rt[i],1,1e5,a[i]);
priority_queue<jj> q;
auto tp=ask(rt[1],1);
q.push({0,tp.fi,1,*lower_bound(v[tp.fi].begin(), v[tp.fi].end(),1)});
dfs(q);
}

upd:感觉刚才好像是睡着了写的,还是把所有代码都沾上来吧

他们去 thu 了,真成留守儿童了。

posted @   lzrG23  阅读(75)  评论(8编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
点击右上角即可分享
微信分享提示