首页 > 其他分享 >QOJ7899 Say Hello to the Future

QOJ7899 Say Hello to the Future

时间:2024-07-28 11:50:12浏览次数:13  
标签:200001 int mx2 Say mid QOJ7899 Future mx1 mx

考虑先求出原序列的方案数

设 \(f_i\) 表示 \(1 \sim i\) 被划分为若干区间的方案数,若一段区间合法当且仅当 \(r-l+1 \ge \max \{a_{l \sim r}\}\),可以发现数据结构难以维护且由于不是最优性问题,考虑 \(\texttt{cdq}\) 分治优化

对于每个分治中心 \(m\),令 \(mxL_i=\max \{a_{i \sim m} \}\),\(mxR=\max \{a_{m+1 \sim i} \}\),那么跨过分治中心的合法区间有 \(r-l+1 \ge \max(mxL_l,mxR_r)\),化简未知量分开有 \(r \ge l + mxL_l -1\),\(l \le r - mxR_r+1\),此时转化为二维偏序,记后者为 \(b_i\),那么把 \([l,m]\) 按照 \(b_i\) 从小到大排序后,使用指针与 BIT 分别维护即可

考虑增加修改,可以发现修改相当于使 \(i\) 没有限制,那么可以求出增量,记 \(g_i\) 为 \(i \sim n\) 的方案数,同样是区间计数,考虑普通分治结构

先考虑 \(p \in [l,m]\) 的增量(\(p\in (m,r]\) 请读者自行思考),若现在左端点枚举到 \(i\),此时 \(p\) 为最大值,由于 \(p\) 没了限制,可以多加维护一个次大值,然后利用最大值和次大值差分求出增量,即减去 \(r \ge l+mx1-1\) 的方案数,加上 \(r \ge l +mx2-1\) 的方案数,然后扫 \((m,r]\) 的时候利用指针维护第一维限制(代码是 vector 维护的,参考了下前最短解),BIT 维护第二维即可

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)/2)
struct node{
	int x,d,v;
	node(int x=0,int d=0,int v=0):x(x),d(d),v(v){}
};
int n,a[200001],b[200001],p[200001];
long long f[210001],g[210001],ans[200001];
vector <node> G[200001];
const int mod=998244353;
struct tree{
	long long n,t[200001];
	void init(int m){n=m;for(int i=1;i<=n;i++)t[i]=0;}
	void add(int x,int v){for(int i=x;i<=n;i+=i&-i)(t[i]+=v)%=mod;}
	long long ask(int x){long long s=0;for(int i=x;i>=1;i-=i&-i)(s+=t[i])%=mod;return s;}
}t;
bool cmp(int x,int y){return b[x]<b[y];}
void cdq(long long *dp,int l,int r){//cdq优化dp
	if(l==r){
		if(a[l]==1) (dp[l]+=dp[l-1])%=mod;
		return;
	}
	cdq(dp,l,mid),t.init(mid-l+1);
	for(int i=mid,mx=0;i>=l;i--) mx=max(mx,a[i]),b[i]=i+mx-1,p[i]=i;
	for(int i=mid+1,mx=0;i<=r;i++) mx=max(mx,a[i]),b[i]=i-mx+1;
	sort(p+l,p+mid+1,cmp);
	for(int i=mid+1,j=l;i<=r;i++){
		while(j<=mid&&i>=b[p[j]]) t.add(p[j]-l+1,dp[p[j]-1]),j++;
		(dp[i]+=t.ask(min(b[i],mid)-l+1))%=mod;
	}
	cdq(dp,mid+1,r);
}
void solve(int l,int r){
	if(l==r){
		if(a[l]!=1) (ans[l]+=f[l-1]*g[l+1])%=mod;
		return;
	}
	solve(l,mid),solve(mid+1,r);
	for(int i=mid,mx=0;i>=l;i--) mx=max(mx,a[i]),b[i]=i+mx-1;
	for(int i=mid+1,mx=0;i<=r;i++) mx=max(mx,a[i]),b[i]=i-mx+1;
	t.init(mid-l+1);
	for(int i=mid+1;i<=r;i++) G[i].clear();
	for(int i=mid,mx1=0,mx2=0,p=0;i>=l;i--){//处理 [l,mid] 的增量
		if(a[i]>mx1) mx2=mx1,mx1=a[i],p=i;
		else if(a[i]>mx2) mx2=a[i];
		if(i+mx1-1<=r) G[max(mid+1,i+mx1-1)].push_back(node(i,p,mod-f[i-1]));//维护 r>=l+mxL[l]-1
		if(i+mx2-1<=r) G[max(mid+1,i+mx2-1)].push_back(node(i,p,f[i-1]));
	}
	for(int i=r;i>mid;i--){
		if(b[i]>=l) t.add(min(b[i],mid)-l+1,g[i+1]);//维护 l<=r-mxR[r]+1
		for(auto j:G[i]) (ans[j.d]+=j.v*(t.ask(mid-l+1)-t.ask(j.x-l)+mod))%=mod;
	}
	t.init(r-mid);
	for(int i=l;i<=mid;i++) G[i].clear();
	for(int i=mid+1,mx1=0,mx2=0,p=0;i<=r;i++){//处理 (mid,r] 的增量
		if(a[i]>mx1) mx2=mx1,mx1=a[i],p=i;
		else if(a[i]>mx2) mx2=a[i];
		if(i-mx1+1>=l) G[min(i-mx1+1,mid)].push_back(node(i,p,mod-g[i+1]));//维护 l<=r-mxR[r]+1
		if(i-mx2+1>=l) G[min(i-mx2+1,mid)].push_back(node(i,p,g[i+1]));
	}
	for(int i=l;i<=mid;i++){
		if(b[i]<=r) t.add(max(mid+1,b[i])-mid,f[i-1]);//维护 r>=l+mxL[l]-1
		for(auto j:G[i]) (ans[j.d]+=j.v*t.ask(j.x-mid))%=mod;
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	f[0]=g[0]=1,cdq(f,1,n),reverse(a+1,a+1+n),cdq(g,1,n),reverse(a+1,a+1+n),reverse(g,g+2+n),solve(1,n);
	for(int i=1;i<=n;i++) printf("%lld ",(f[n]+ans[i])%mod);
	return 0;
}

标签:200001,int,mx2,Say,mid,QOJ7899,Future,mx1,mx
From: https://www.cnblogs.com/zyxawa/p/18328054

相关文章

  • 关于 DataFrame 连接行为的 FutureWarning
    我正在从包含多个页面的API检索数据。初始页面中的必填字段被添加到pandas数据帧-在我的代码中,该变量最初定义为df|||.从原始的API响应中,我能够了解完整响应中的页面总数,因此我可以创建一个循环来迭代页面并按顺序提取所有信息。......
  • 为什么警告:FutureWarning:设置不兼容的数据类型的项目已被弃用,并且会在 pandas 的未来
    鉴于这种情况,我不明白为什么要提出这个特殊警告。将函数应用于数字系列时,它会引发“FutureWarning:设置不兼容dtype的项目已被弃用,并将在pandas的未来版本中引发错误。值'[011...100]'具有dtype与int32不兼容,请先显式转换为兼容的数据类型。"这是正在应用的......
  • Java CompletableFuture 异步超时实现探索
    简介JDK8中CompletableFuture没有超时中断任务的能力。现有做法强依赖任务自身的超时实现。本文提出一种异步超时实现方案,解决上述问题。前言JDK8是一次重大的版本升级,新增了非常多的特性,其中之一便是CompletableFuture。自此从JDK层面真正意义上的支持了基于事件的......
  • netty入门-4 Channel与ChannelFuture
    Channel基本类似于NIO中的Channel概念。作为读写数据的通道。常见方法close()可以用来关闭channelcloseFuture()用来处理channel的关闭sync方法作用是同步等待channel关闭而addListener方法是异步等待channel关闭pipeline()方法添加处理器write()方法......
  • Java中的异步编程与CompletableFuture应用
    Java中的异步编程与CompletableFuture应用大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代Java编程中,异步编程变得越来越重要,它可以帮助我们提高应用程序的响应速度和性能。CompletableFuture是Java8引入的一个强大工具,它简化了异步编程,使得......
  • CompletableFuture异步编程—Java8 (附代码举例)
    ......
  • C++11标准库 未来体 <future> 梳理
    目录<future>future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程:async模板函数例程:shared_future模板类<future>标准库提供了一些工具来获取异步任务(即在单独的线程中启动的函数)的返回值,并捕捉其所抛出的异常。这些值在共享状态中传递,其中异步任务可以......
  • Java中的CompletableFuture详解
    Java中的CompletableFuture详解大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代Java编程中,异步编程变得越来越重要。Java8引入了CompletableFuture,它极大地简化了异步编程的复杂性。CompletableFuture不仅支持异步操作,还提供了丰富的API来处理异步......
  • C++11标准库<chrono>、<future>、 <atomic>、<condition_variable>、<mutex>、<t
    目录<chrono>时间间隔duration常用的duration时间点time_point时钟system_clock&steady_clocksystem_clock代码举例steady_clock(秒表)例程:转换函数1.duration_castDescription:duration支持隐式转换的规则2.time_point_cast<thread>this_thread命名空间1.get_id()2.sleep_f......
  • 异步编程秘籍:一探std::future的魔法,让代码飞起来
    ......