首页 > 其他分享 >P5979 [PA2014] Druzyny 题解

P5979 [PA2014] Druzyny 题解

时间:2024-09-19 23:34:26浏览次数:12  
标签:int 题解 PA2014 mid Druzyny 端点 text rep define

对于一个固定的右端点 \(r\),左端点 \(l\) 合法当且仅当 \(\max(d_l,d_{l+1},\dots d_r)\le r-l+1 \le\min(c_l,c_{l+1},\dots,c_r)\)。

容易得到一个很朴素的 dp:记 \(f_i\) 表示前 \(i\) 个位置可以分成的组的数目的最大值,\(g_i\) 表示有多少种分组方案能达到最大值,直接枚举左端点转移,时间复杂度 \(\mathcal O(n^2)\)。转移点不是连续的,不好直接优化。

考虑对这个 dp 进行一个分治,对于每个分治的区间 \([l,r]\) 处理 \(f_{[l,\text{mid}]},g_{[l,\text{mid}]}\) 对 \(f_{[\text{mid}+1,r]},g_{[\text{mid}+1,r]}\) 的贡献。发现 \(c\) 对每个右端点的限制是只能取某个后缀的左端点,可以直接二分出这个后缀,接下来只要考虑 \(d\) 的限制。

很容易想到倒着枚举 \([l,\text{mid}]\) 中的每个位置,维护 \(d\) 的最大值,可以得到一个右端点的位置 \(\ge \max(d_{[l,\text{mid}]})+l-1\) 的限制。考虑对 \([\text{mid}+1,r]\) 每个位置建一个桶,在这个限制的对应位置处插入这个左端点。接下来正着枚举 \([\text{mid}+1,r]\) 中的每个位置,把桶内的位置插入线段树。对于每个右端点也可以得到一个类似的限制,在线段树上查询即可,最后更新一下就做完了。

时间复杂度 \(\mathcal O(n\log^2n)\),参考代码:

#include<bits/stdc++.h>
#define ll long long
#define mxn 1000003
#define md 1000000007
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
#define drep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
struct node{
	ll a,c;
}f[mxn],t[mxn<<2];
int n,lg[mxn],ps[mxn],a[mxn],b[20][mxn];
vector<int>s[mxn];
const int INF=1e9;
node operator+(node x,node y){
	return {max(x.a,y.a),((x.a>=y.a?x.c:0)+(y.a>=x.a?y.c:0))%md};
}
int ask2(int l,int r){
	int k=lg[r-l+1];
	return min(b[k][l],b[k][r-(1<<k)+1]);
}
void change(int p,int x,node y,int l,int r){
	if(l==r){t[p]=y;return;}
	int mid=(l+r)>>1;
	if(x<=mid)change(p<<1,x,y,l,mid);
	else change(p<<1|1,x,y,mid+1,r);
	t[p]=t[p<<1]+t[p<<1|1];
}
node ask(int p,int l,int r,int L,int R){
	if(l<=L&&R<=r)return t[p];
	int mid=(L+R)>>1;
	if(l<=mid&&r>mid)return ask(p<<1,l,r,L,mid)+ask(p<<1|1,l,r,mid+1,R);
	if(l<=mid)return ask(p<<1,l,r,L,mid);
	return ask(p<<1|1,l,r,mid+1,R);
}
void build(int p,int l,int r){
	t[p]={-INF,0};
	if(l==r)return;
	int mid=(l+r)>>1;
	build(p<<1,l,mid);build(p<<1|1,mid+1,r);
}
void solve(int l,int r){
	if(l==r)return;
	int mid=(l+r)>>1;
	solve(l,mid);
	rep(i,mid+1,r)s[i].clear();
	int mx=0;
	drep(i,mid,l){
		if(mx+i<=r)s[max(mx+i,mid+1)].pb(i);
		mx=max(mx,a[i]);
	}
	mx=0;
	rep(i,mid+1,r){
		mx=max(mx,a[i]);
		for(int j:s[i])change(1,j,{f[j].a+1,f[j].c},0,n);
		int L=max(ps[i]-1,l),R=min(i-mx,mid);
		if(L<=R)f[i]=f[i]+ask(1,L,R,0,n);
	}
	rep(i,l,mid)change(1,i,{-INF,0},0,n);
	solve(mid+1,r);
}
signed main(){
	scanf("%d",&n);
	rep(i,2,n)lg[i]=lg[i>>1]+1;
	rep(i,1,n)scanf("%d%d",&a[i],&b[0][i]);
	rept(k,1,20){
		rep(i,1,n-(1<<k)+1){
			b[k][i]=min(b[k-1][i],b[k-1][i+(1<<(k-1))]);
		}
	}
	rep(i,1,n){
		int l=1,r=i;
		while(l<r){
			int mid=(l+r)>>1;
			if(ask2(mid,i)>=i-mid+1)r=mid;
			else l=mid+1;
		}
		ps[i]=l;
	}
	f[0].c=1;
	rep(i,1,n)f[i].a=-INF;
	build(1,0,n);
	solve(0,n);
	if(f[n].a<=0)puts("NIE");
	else cout<<f[n].a<<" "<<f[n].c;
	return 0;
}

标签:int,题解,PA2014,mid,Druzyny,端点,text,rep,define
From: https://www.cnblogs.com/zifanoi/p/18421588

相关文章

  • CF2004G 题解
    题意定义关于数字串\(s\)的函数\(f(s)\)表示将\(t\)切分为\(m\)段,要求\(m\)是偶数,假设这些字符串分别为\(t_1,t_2,\ldots,t_m\),有\(s=t_1+t_2+\ldots+t_m\)。定义\(A^x\)表示\(\underbrace{AA\ldotsAA}_{x~\text{times}}\),求一种划分方式,使得\(t_2^......
  • P1108 低价购买 题解
    这题在求最长下降子序列的基础上加了一个求方案数的要求,这就让这道题目变难了很多。我们考虑我们在求最长下降子序列的时候,总是从这一位,要么重新开始计数,要么只和前面的有关,所以前面的信息完全丢失了,无法判断有多少方案,所以我们就要针对前面的方案数设计一个dp来统计。可以称之......
  • 题解:CF1906F Maximize The Value
    可以在cnblog中阅读。见这种题比较少,写篇题解加深印象。如果直接上数据结构维护数组,似乎没有好的办法处理操作序列的一个子段。那不妨转变思路,对操作序列上数据结构维护。假设顺序进行每个修改操作,我们用时间表示修改操作的编号,位置表示数组的下标,则常见的维护序列的数据结构......
  • 蓝桥杯十五届软件赛C++B组题解
    最近蓝桥杯官网已经把十五届题目上架了,我会尽快的将题解发出来,没有发的过段时间再补。​​​​​​​数字接龙一个很鹅心的搜索题,一不注意就会写错,比赛的时候写不来,题目上架后也WA了两个样例才过。题目大意:也就是说从(1,1)开始 ,下一步路的数据总是要比当前数据大1,超过k就......
  • P2051 [AHOI2009] 中国象棋 题解
    DP好题?首先确定,每一行/列只能放至多两个棋子,这么少,所以我们的状态肯定和棋子数有关。由于我们不关注具体的方案数,所以我们不妨只关心对应棋子数量的行/列的数量。同时,由于考虑行和列都是一样的,所以我们不妨用行递推。所以我们设$\dp_{i,j,k}\$表示当前放到第\(i\)行,有\(......
  • Capital许可使用常见问题解答
    在使用Capital软件的过程中,许多用户可能会遇到关于许可使用的各种问题。为了帮助大家更好地理解和合规使用Capital软件,我们整理了一份常见问题解答,希望能为您提供有价值的参考。一、Capital许可证的类型有哪些?Capital提供多种许可证类型,包括永久许可证、订阅许可证等。永久许可......
  • 【题解】Solution Set - NOIP2024集训Day32 数位 dp
    【题解】SolutionSet-NOIP2024集训Day32数位dphttps://www.becoder.com.cn/contest/5537order:1,3,5,6,2,4「SDOI2013」淘金就是要算前\(k\)大的和。考虑一个位置\((i,j)\)在变化完了之后的金子个数。(也即逆变换。设:\(f^\prime(x)\)表示在\(1\simN\)范围内,数位......
  • 【洛谷 P5730】【深基5.例10】显示屏 题解(数组+循环)
    【深基5.例10】显示屏题目描述液晶屏上,每个阿拉伯数字都是可以显示成的点阵的(其中X表示亮点,.表示暗点)。现在给出数字位数(不超过)和一串数字,要求输出这些数字在显示屏上的效果。数字的显示方式如同样例输出,注意每个数字之间都有一列间隔。输入格式第一行输入一个正整数,表示数......
  • luogu-P10596题解
    简要题意一个有\(N\)个元素的集合有\(2N\)个不同子集(包含空集),现在要在这\(2N\)个集合中取出若干集合(至少一个),使得它们的交集的元素个数为\(K\),求取法的方案数,答案模\(10^9+7\)。数据范围:\(1\leK\leN\le10^6\)。题解我们设\(f(i)\)表示选出子集大小恰好为\(i\)的......
  • 【洛谷】P11062 【MX-X4-T2】「Jason-1」加法 的题解
    【洛谷】P11062【MX-X4-T2】「Jason-1」加法的题解题目传送门离CSP初赛只剩两天了,祝各位OIersrp++!!!题解挺有意思的一道思维题,不过比赛的时候没想出来。需要分类讨论两种情况:当a......