模拟题大集合(2)

2021-09-16 19:41:18 星期四
淦,上一个大集合卡展了,写博客写到一半就崩溃,崩溃了好几次了,于是新开了一个

打怪

打正解是不可能打正解的~~
这个是考完了用乱搞贪心水掉的,然后拿沈sir程序造hack数据hack自己结果把沈sir hack了...数据是XIN造的,把我也hack了,本来以为只有自己会无脸测试点分治结果沈sir也来了个if(n<=10)...虽然沈sir不偷懒改改就能过吧...

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("fittest.in","r",stdin);freopen("fittest.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline ll min(ll a,ll b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=3e5+10;
	struct pt{
		int cheng;db chu;
		int c,a,d,id;
	}p[N];int n,b,sum;bool vis[N];ll ans=1e18;
	inline bool com(pt a,pt b){return a.cheng==b.cheng?a.a>b.a:a.cheng>b.cheng;}
	inline bool Com(pt a,pt b){return a.chu<b.chu;}
	inline void solve(){
		std::sort(p+1,p+n+1,Com);
		F(i,1,n)F(j,i+1,n){
			vis[i]=vis[j]=1;
			int sum=0;ll aans=0;
			F(k,1,n)if(!vis[k])sum+=p[k].a;
			F(k,1,n)if(!vis[k]){
				sum-=p[k].a;aans+=1ll*p[k].a*p[k].c;
				aans+=1ll*sum*(p[k].c+1);
			}
			vis[i]=vis[j]=0;
			ans=min(ans,aans);
		}pi(ans);
	}
	inline short main(){
		file();
		n=read();b=read();
		F(i,1,n){
			p[i].id=i;
			p[i].a=read(),p[i].d=read();
			sum+=p[i].a;
			p[i].c=(p[i].d-1)/b;
			p[i].cheng=p[i].c*p[i].a;
			p[i].chu=(db)1.0*(p[i].c+1)/(db)p[i].a;
		}
		if(n<=200){solve();return 0;}
		std::sort(p+1,p+n+1,com);
		vis[p[1].id]=vis[p[2].id]=1;
		sum-=p[1].a,sum-=p[2].a;
		std::sort(p+1,p+n+1,Com);ans=0;
		F(i,1,n)if(!vis[p[i].id]){
			sum-=p[i].a;ans+=1ll*p[i].a*p[i].c;
			ans+=1ll*sum*(p[i].c+1);
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

选择

首先每个点连接的边<=10,n<=1e3于是可以状压dp,考试时想到了这个,但是不会处理经过根节点的路径和叶子节点的关系,
可以尝试状压表示经过根节点最多路径有几条,尝试删去某个子树,如果删掉之后答案没变,那么可以将这个子树对应的儿子的延伸结点复制过来,其他的就是普通树形dp统计上子树内的路径即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("select.in","r",stdin);freopen("select.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e3+10;
	int head[N],co,n,m,id[N];
	int f[N][1<<10],dp[N];
	struct pair{int a,b;};
	bool graph[N][N];pair rec[N];int cnt,Rec[N],Cnt;
	std::vector<int>son[N],touch[N];
	struct node{
		int next,to;
	}e[N<<1];
	inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
	inline void dfs1(int k,int fa){
		int tot=0;
		for(register int i=head[k],j;i;i=e[i].next){
			if((j=e[i].to)==fa)continue;
			++tot;son[k].push_back(j);
			id[j]=tot;
			dfs1(j,k);
		}
	}
	inline void dfs(int k){
		touch[k].push_back(k);
		for(auto j:son[k])dfs(j),dp[k]+=dp[j];
		cnt=Cnt=0;
		for(auto i:son[k])
			for(auto j:son[k])if(id[i]<id[j]){
				for(auto l:touch[i])
					for(auto o:touch[j])
						if(graph[l][o])
							{rec[++cnt]=(pair){i,j};goto ed;}
				ed:;
			}
		for(auto i:son[k])
			for(auto j:touch[i])
				if(graph[k][j])Rec[++Cnt]=i;
		int maxn=0;
		F(i,0,(1<<son[k].size())-1){
			maxn=max(maxn,f[k][i]);
			F(j,1,cnt){
				int u=rec[j].a,v=rec[j].b;
				if(i&(1<<(id[u]-1))||i&(1<<(id[v]-1)))continue;
				f[k][i|(1<<(id[u]-1))|(1<<(id[v]-1))]=max(f[k][i|(1<<(id[u]-1))|(1<<(id[v]-1))],f[k][i]+1);
			}
			F(j,1,Cnt){
				int u=Rec[j];
				if(i&(1<<(id[u]-1)))continue;
				f[k][i|(1<<(id[u]-1))]=max(f[k][i|(1<<(id[u]-1))],f[k][i]+1);
			}
		}dp[k]+=maxn;
		for(auto x:son[k]){
			int Maxn=0;
			F(i,0,(1<<son[k].size())-1)f[k][i]=0;
			F(i,0,(1<<son[k].size())-1){
				Maxn=max(Maxn,f[k][i]);
				F(j,1,cnt){
					int u=rec[j].a,v=rec[j].b;
					if(u==x||v==x)continue;
					if(i&(1<<(id[u]-1))||i&(1<<(id[v]-1)))continue;
					f[k][i|(1<<(id[u]-1))|(1<<(id[v]-1))]=max(f[k][i|(1<<(id[u]-1))|(1<<(id[v]-1))],f[k][i]+1);
				}
				F(j,1,Cnt){
					int u=Rec[j];
					if(u==x)continue;
					if(i&(1<<(id[u]-1)))continue;
					f[k][i|(1<<(id[u]-1))]=max(f[k][i|(1<<(id[u]-1))],f[k][i]+1);
				}
			}
			if(Maxn==maxn)for(auto i:touch[x])touch[k].push_back(i);
		}
	}
	inline short main(){
		file();
		n=read();
		F(i,1,n-1){
			int x=read(),y=read();
			add(x,y);add(y,x);
		}dfs1(1,0);
		m=read();
		F(i,1,m){
			int u=read(),v=read();
			graph[u][v]=graph[v][u]=1;
		}dfs(1);
		pi(dp[1]);
		return 0;
	}
}
signed main(){return EMT::main();}

上一篇:[模板]笛卡尔树


下一篇:界面数据结构转换存储