ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

远古离散题

2022-03-28 10:31:42  阅读:188  来源: 互联网

标签:10 int 奇偶性 离散 leq 远古 include dp


前言

因为之前做法假了或者代码写太丑了,还不如重写一遍。
之前CSDN过河的代码会被洛谷的HACK数据HACK掉QWQ。


过河

题目链接:P1052

题目大意

有一条河,起点为 \(0\),终点为 \(L(L\leq 10^9)\),其中一些位置有石头。

有一只青蛙一次可以跳 \([l,r](r\leq 10)\) 的距离,如果它想从起点跳到 \(\geq L\) 的点,至少需要越过多少个石头。

思路

有一个很简单的方法,设 \(dp[i]\) 表示跳到 \(i\) 时至少需要越过多少个石头,

那么 \(\large dp[i]=\min_{j=l}^r\{dp[i-j]\}+stone[i]\),其中 \(stone[i]\) 表示第 \(i\) 个点是否为石头。

最后的答案就是 \(\large \min_{j=0}^{r-1}dp[L+j]\),这样时间复杂度为 \(O(r(L+r))\),主要是要将 \(L\) 的复杂度变小。

考虑将石头的位置离散,并且只要跳过所有的石头就可以随便跳,所以答案只与石头的位置有关。

可以发现不小于 \(72\) 的步数都能被表示出来,那么只要步数超过 \(72\) 就可以缩成 \(72\)。

具体可以沿用小凯的疑惑的结论,不能表示的最大数为 \(r*(r-1)-r-(r-1)\)。

那么这样 \(L\) 就被缩小成了 \(O(mr^2)\) 量级,那么最后的时间复杂度就是 \(O(mr^3)\)

代码

#include <iostream>
#include <algorithm>
using namespace std;
const int N=111,lim=72; int ans=0x3f3f3f3f;
int L,l,r,n,a[N],stone[N*72],dp[N*72];
int main(){
	ios::sync_with_stdio(0);
	cin>>L>>l>>r>>n;
	for (int i=1;i<=n;++i) cin>>a[i];
	sort(a+1,a+1+n);//排序 
	if (l==r){//如果 l=r 要特判 
		ans=0;
		for (int i=1;i<=n;++i)
		    if (a[i]%l==0) ++ans;
		cout<<ans;
		return 0;
	}
	for (int i=1,lst=0;i<=n;++i){
		int now=min(a[i]-lst,lim);//石头间距离超过72可以缩成72
		lst=a[i],a[i]=a[i-1]+now;
	}
	for (int i=1;i<=n;++i) stone[a[i]]=1;
	for (int i=1;i<a[n]+r;++i){
		dp[i]=0x3f3f3f3f;
		for (int j=l;j<=r;++j)//dp[i]=min{dp[i-j]}+1
		if (i>=j)
		    dp[i]=min(dp[i],dp[i-j]);
		dp[i]+=stone[i];
	}
	for (int i=a[n];i<a[n]+r;++i) ans=min(ans,dp[i]);
	cout<<ans;
	return 0;
}

程序自动分析

题目链接:P1955

题目大意

多组数据,有若干个变量,\(n\) 条限制,形如 \(x_i\neq x_j\) 或者 \(x_i=x_j\),问这些变量是否能满足所有限制。

\(n\leq 10^6,i,j\leq 10^9\)

思路

先考虑 \(x_i=x_j\) 的限制,再考虑 \(x_i\neq x_j\) 的限制,按照 \(x_i=x_j\) 的限制将 \(i,j\) 缩成一个连通块,

那么实际上只需要在 \(x_i\neq x_j\) 的时候判断 \(i,j\) 是否不在同一连通块,如果在同一连通块就无解。

然而 \(i,j\) 的范围比较大,不过实际上可用的 \(i,j\) 不超过 \(2n\) 个,那么直接将编号离散即可。

代码

#include <iostream>
#include <algorithm>
using namespace std;
const int N=1000011;
int x[N],y[N],opt[N],b[N<<1],rk[N],n,Test,flag,f[N],m;
bool cmp(int x,int y){return opt[x]>opt[y];}//把xi=xj的限制放在前面
int find_root(int u){//并查集
    if (f[u]==u) return u;
    return f[u]=find_root(f[u]);
}
int main(){
	ios::sync_with_stdio(0);
	for (cin>>Test;Test;--Test){
		cin>>n,flag=0;
		for (int i=1;i<=n;++i){
			cin>>x[i]>>y[i]>>opt[i];
			b[i]=x[i],b[i+n]=y[i],rk[i]=i;
		}
		sort(b+1,b+1+n*2),sort(rk+1,rk+1+n,cmp);
		m=unique(b+1,b+1+n*2)-b-1;//将xi,xj离散
		for (int i=1;i<=m;++i) f[i]=i;
		for (int i=1;i<=n;++i){
			x[rk[i]]=lower_bound(b+1,b+1+m,x[rk[i]])-b;
			y[rk[i]]=lower_bound(b+1,b+1+m,y[rk[i]])-b;
			int fx=find_root(x[rk[i]]),fy=find_root(y[rk[i]]);
			if (opt[rk[i]]&&fx!=fy) f[fx]=fy;//如果xi=xj且当前不处于同一连通块就连起来
			    else if (!opt[rk[i]]&&fx==fy) {flag=1; break;}
            //如果xi不等于xj且在同一连通块则无解
		}
		if (flag) cout<<"NO"<<endl;
		    else cout<<"YES"<<endl;
	}
	return 0;
}

Parity Game

题目链接:P5937

题目大意

有一个长度为 \(n\) 的 \(01\) 串 \(a\),现在有 \(m\) 条限制形如 \(a[l\sim r]\) 中有奇数个 \(1\) 或者偶数个 \(1\),

是否存在第 \(i\) 条限制不符合要求,并且前 \(i-1\) 条限制均能符合要求。

\(n\leq 10^9,m\leq 5*10^3\)

思路

限制其实就是 \(s[r]-s[l-1]\) 的奇偶性,可以考虑边带权并查集,处理出每个位置到并查集根的奇偶性 \(s'[x]\),那么每次合并的时候实际上 \(x\) 的根节点到 \(y\) 的根节点的奇偶性就是 \(s'[x]\) \(xor\) \(s'[y]\) \(xor\) \(z\)。

然后路径压缩的时候同样维护到根节点的奇偶性,但是 \(n\) 太大,考虑可用的位置不超过 \(2m\) 个,直接离散即可。

代码

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int N=10011; string S;
int n,m,b[N],x[N],y[N],z[N],f[N],s[N];
int find_root(int u){
    if (f[u]==u) return u;
    int U=find_root(f[u]);
    s[u]^=s[f[u]];//原来s[u]是到f[u]的奇偶性,异或s[f[u]]后是到根节点的奇偶性 
    return f[u]=U;
}
int main(){
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for (int i=1;i<=m;++i){
		cin>>x[i]>>y[i]>>S;
		b[i]=--x[i],b[i+m]=y[i];
		if (S[0]=='o') z[i]=1; 
	}
	sort(b+1,b+1+m*2),n=unique(b+1,b+1+m*2)-b-1;//离散 
	for (int i=1;i<=n;++i) f[i]=i;
	for (int i=1;i<=m;++i){
		x[i]=lower_bound(b+1,b+1+n,x[i])-b;
		y[i]=lower_bound(b+1,b+1+n,y[i])-b;
		int fx=find_root(x[i]),fy=find_root(y[i]);
		if (fx==fy){
			if ((s[x[i]]^s[y[i]]^z[i])&1){
			//由于异或的自反性,s[x[i]]^s[y[i]]得到的是x[i]到y[i]的奇偶性,必须与z[i]相同 
				cout<<i-1;
				return 0;
			}
		}else f[fx]=fy,s[fx]=s[x[i]]^s[y[i]]^z[i];//fx到fy的奇偶性
	}
	cout<<m;
	return 0;
}

标签:10,int,奇偶性,离散,leq,远古,include,dp
来源: https://www.cnblogs.com/Spare-No-Effort/p/16065896.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有