R6饮料AK赛(NOIP模拟赛)/省选专练HDU 5713 K个联通块

R6饮料AK赛(NOIP模拟赛)/省选专练HDU 5713 K个联通块_第1张图片

R6饮料AK赛(NOIP模拟赛)/省选专练HDU 5713 K个联通块_第2张图片

R6饮料AK赛(NOIP模拟赛)/省选专练HDU 5713 K个联通块_第3张图片我好菜啊100+60+30

滚犊子吧,两天加起来才410搞个屁我一年前都可以考400

不说了,题毕竟比较难

T1还是水题但是比昨天难

这是一个开绝对值不等式的题。

根据对奇数和偶数的最优根的归纳一定有一个解是在原址上

于是上界OnLogn

水过

#include
#include
#include
#include
#include
using namespace std;
typedef int INT;
#define int long long
const int N=2e5+100;
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int sum[N]={};
int a[N]={};
int n;
int ans=1e17+7;
INT main(){
	freopen("snake.in","r",stdin);
	freopen("snake.out","w",stdout);
	read(n);
	sum[0]=0;
	for(int i=1;i<=n;i++){
		read(a[i]);
		a[i]=a[i]-i;
//		sum[i]=sum[i-1]+a[i];
	}
	sort(a+1,a+1+n);
//	for(int i=1;i<=n;i++){
//		cout<

T2对我这种弱鸡来说就有点难度了

这是一个结论题

但是虽然我推出了重要结论但是还是没有满分

30分:枚举三个断点

重要结论:

枚举中间部分断点

左右两端寻找尽可能差小的答案值

显然sum的前缀和是单谷函数

你可以三分值或者二分一阶导函数

考试60分代码

#include
#include
#include
#include
#include
using namespace std;
typedef int INT;
#define int long long
const int N=2e5+10;
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int a[N]={};
int sum[N]={};
int n;
int ans=1e17+9;
struct Node{
	int minsum,maxsum;
};
Node getsum(int L,int R){
	int l=L;
	int r=R;
	int ans=1e16+7;
	Node ret;
	ret.maxsum=-1;
	ret.minsum=1e17;
	for(int i=l;i(abs((sum[i]-sum[L-1])-(sum[R]-sum[i])))){
			ans=abs((sum[i]-sum[L-1])-(sum[R]-sum[i]));
//			cout<

AC代码:

#include
#include
#include
#include
#include
using namespace std;
typedef int INT;
#define int long long
const int N=2e5+10;
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int a[N]={};
int sum[N]={};
int n;
int ans=1e17+9;
struct Node{
	int minsum,maxsum;
};
Node getsuml(int L,int R){
	int l=L;
	int r=R-1;
	int ans=1e16+7;
	int s=sum[R]-sum[L-1];
	Node ret;
	while(l^r){
		int mid=(l+r)/2;
		if(abs(sum[mid]*2-s)

注意此处的二分写法新颖

实际乘二是指的右边除二

原理是我判断其离平均值有多近。

这等价于俩边之差更接近

T3

HDU5713 K个联通块

省选难度状压DP

你不能枚举边

但是枚举点的复杂度是可行的

于是思考一:状压DP

定义状态:

dp(i,j)i:当前有i个联通块 j:点集状态为j即一个状压状态0100101010之类的

f(i)i:一个状压状态表示该点集时可以断掉的边的种类使这个点集依旧连通

G(i)i:一个状压状态表示一个点集,目的是选择后断开(容斥原理)

用全集减补集求出F

考试30分代码

#include
#include
#include
#include
#include
using namespace std;
const int mod=1e9+9;
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
const int N=20;
struct Front_star{
	int u,v,nxt,del;
}e[N*N];
int cnt=0;
int first[N]={};
void add(int u,int v){
	cnt++;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].nxt=first[u];
	e[cnt].del=0;
	first[u]=cnt;
}
int n,m,k;
int ans=0;
int fa[15]={};
inline int getfa(int x){
	if(fa[x]==x)return x;
	else return fa[x]=getfa(fa[x]);
}
inline void Union(int x,int y){
	int dx=getfa(x);
	int dy=getfa(y);
	fa[dy]=dx;
}
int check(){		
	
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	for(int i=1;i<=cnt;i++){
		if(!e[i].del)
			Union(e[i].u,e[i].v);
	}
	for(int i=1;i<=n;i++){
		getfa(i);
	}
	sort(fa+1,fa+1+n);
	int len=unique(fa+1,fa+1+n)-fa-1;
	if(len==k){
//		for(int i=1;i<=cnt;i++){
//			cout<cnt)return;
	e[tim].del=1;
	dfs(tim+1);
	e[tim].del=0;
	dfs(tim+1);
}
int main(){
	freopen("sarsae.in","r",stdin);
	freopen("sarsae.out","w",stdout);
	read(n);
	read(m);
	read(k);
	for(int i=1;i<=m;i++){
		int u,v;
		read(u);
		read(v);
		add(u,v);
	}
	dfs(1);
	cout<

修改后代码

dp更新是一个背包原理

#include
#include
#include
#include
#include
using namespace std;
typedef int INT;
#define int long long 
inline void read(int &x){
	x=0;
	char ch=getchar();
	int f=1;
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=f;
}
int f2[1000+20]={};
const int mod=1e9+9;
void Pre(){
	f2[0]=1;
	for(int i=1;i<=1000;i++){
		f2[i]=f2[i-1]*2%mod;
	}
}
const int N=15;
int n,m,k;
int maxn;
int dp[N][1<

你可能感兴趣的:(OI套题,智商题,并查集(按秩合并/路径压缩),二分(三分/多分/黄金分治),动态规划)