• 测试「20201013测试总结」


    连着两次考试小于机房平均分了/kk,不努点力看来是不行了。


    T1

    将图分成一个团和一个独立集的方案数,正解是爆搜/fad。

    然而把图建出来反而不好搜,于是不建图,只枚举每个点在团中还是在独立集中。这样看起来是 (O(2^N)) ,但实际上可以剪枝剪掉大部分不合法方案。

    考场上时间没分配好,打了2h暴力无果。

    考后bitset爆艹标算

    ( ext{Code}:)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <bitset>
    using namespace std;
    typedef long long lxl;
    const int maxn=1e3+5,maxm=maxn*maxn;
    const lxl mod=1000003;
    
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1=buf,*p2=buf;
    template <typename T>
    inline void read(T &x)
    {
    	x=0;T f=1;char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	x*=f;
    }
    
    int n,m;
    bool vis[maxn];
    bitset<maxn> bes[maxn],worker,part;
    int ans;
    
    inline void dfs(int x)
    {
    	if(x==n+1) return ans+=(worker.any()&&part.any()),void();
    	if((worker|bes[x])==bes[x])
    	{
    		worker.set(x);
    		dfs(x+1);
    		worker.reset(x);
    	}
    	if(!(part&bes[x]).any())
    	{
    		part.set(x);
    		dfs(x+1);
    		part.reset(x);
    	}
    }
    
    int main()
    {
    	// freopen("party.in","r",stdin);
    	// freopen("party.out","w",stdout);
    	int T;read(T);
    	while(T--)
    	{
    		read(n),read(m);
    		for(int i=1;i<=n;++i) bes[i].reset();
    		worker.reset();part.reset();
    		for(int i=1,u,v;i<=m;++i)
    		{
    			read(u),read(v);
    			bes[u].set(v);
    			bes[v].set(u);
    		}
    		ans=0;
    		dfs(1);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    T2

    枚举小N选取的前缀,发现小A一定会选取最大后缀,那么直接上线段树就好了。

    但是线段树用在这道题上是多余的,正解复杂度是 (O(n))

    T1打了2h暴力无果后,开了T2,花了不到1h过了T2。

    ( ext{Code}:)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <climits>
    #define Rint register int
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long lxl;
    const int maxn=1e6+5;
    
    template <typename T>
    inline void read(T &x)
    {
    	x=0;T f=1;char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	x*=f;
    }
    
    int n;
    lxl A,B,a[maxn];
    
    struct node
    {
    	int l,r;
    	lxl rmax,sum;
    	node(int l,int r,lxl rmax,lxl sum)
    		:l(l),r(r),rmax(rmax),sum(sum){}
    	node(){}
    	inline node operator + (const node &T)const
    	{
    		return node(l,T.r,max(T.rmax,rmax+T.sum),sum+T.sum);
    	}
    };
    
    struct Segment_Tree
    {
    	node tree[maxn<<2];
    	#define ls (p<<1)
    	#define rs (p<<1|1)
    	inline void init(int p,lxl d)
    	{
    		tree[p].sum=d;
    		tree[p].rmax=max(d,0ll);
    	}
    	void build(int p,int l,int r)
    	{
    		tree[p]=node(l,r,0,0);
    		if(l==r) return init(p,a[l]),void();
    		int mid=(l+r)>>1;
    		build(ls,l,mid);
    		build(rs,mid+1,r);
    		tree[p]=tree[ls]+tree[rs];
    	}
    	void modify(int p,int ps,lxl d)
    	{
    		int l=tree[p].l,r=tree[p].r;
    		if(l==r) return init(p,d),void();
    		int mid=(l+r)>>1;
    		if(ps<=mid) modify(ls,ps,d);
    		else modify(rs,ps,d);
    		tree[p]=tree[ls]+tree[rs];
    	}
    }st;
    
    int main()
    {
    	// freopen("game.in","r",stdin);
    	// freopen("game.out","w",stdout);
    	read(n),read(A),read(B);
    	for(int i=1;i<=n;++i)
    		read(a[i]);
    	st.build(1,1,n);
    	lxl ans=LLONG_MIN;
    	for(int i=0;i<=n;++i)
    	{
    		if(i>=1) st.modify(1,i,a[i]*=-A);
    		node res=st.tree[1];
    		ans=max(ans,res.sum-res.rmax-res.rmax*B);
    //		res=st.tree[1];
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    T3

    第一轮的困扰值可以直接放在边上。

    第二轮也可以放在边上。考虑边 (uleftrightarrow v) 对它两端点的影响:

    • 若先在 (u) 上放一个居民,再在 (v) 上放一个居民,则困扰值为 (F_u imes T_v+F_v imes (T_u+1))
    • 若先在 (v) 上放一个居民,再在 (u) 上放一个居民,则困扰值为 (F_v imes T_u+F_u imes (T_v+1))

    将两式相减可以发现:先在 (F) 值大的城市上放居民的困扰值较小。于是可以贪心地放居民,由于决策只与 (F_u)(F_v) 的大小有关,不难发现,最优的方案是先将 (F) 值大的城市放满居民,再放另一个城市。若 (F_u>F_v) ,则这条边造成的困扰值为:

    [F_u imes(U_u-T_u) imes T_v+F_v imes U_u imes (U_v-T_v) ]

    否则 (F_u<F_v) 同理。

    建出图跑最小生成树即可。

    考试最后30min才开T3,所以没怎么思考,不过题解的这种转化思想是ao的,还是有收获。

    ( ext{Code}:)

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define Rint register int
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long lxl;
    const int maxn=55;
    
    template <typename T>
    inline void read(T &x)
    {
    	x=0;T f=1;char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	x*=f;
    }
    
    struct edge
    {
    	int u,v;
    	lxl w;
    	edge(int u,int v,lxl w):u(u),v(v),w(w){}
    	edge(){}
    	inline bool operator < (const edge &T)const
    	{
    		return w<T.w;
    	}
    }e[maxn*maxn];
    int ecnt;
    
    int n,fa[maxn];
    lxl T[maxn],U[maxn],F[maxn],C,ans;
    char G[maxn][maxn];
    
    inline int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    
    inline lxl calcu(int i,int j)
    {
    	if(F[i]<F[j]) swap(i,j);
    	return F[i]*(U[i]-T[i])*T[j]+F[j]*U[i]*(U[j]-T[j]);
    }
    
    inline bool merge(int u,int v)
    {
    	int x=find(u),y=find(v);
    	if(x==y) return false;
    	fa[x]=y;
    	return true;
    }
    
    int main()
    {
    	// freopen("reconstruction.in","r",stdin);
    	// freopen("reconstruction.out","w",stdout);
    	read(n);
    	for(int i=1;i<=n;++i) read(T[i]);
    	for(int i=1;i<=n;++i) read(U[i]);
    	for(int i=1;i<=n;++i) read(F[i]);
    	for(int i=1;i<=n;++i)
    		scanf(" %s
    ",G[i]+1);
    	for(int i=1;i<=n;++i)
    		fa[i]=i,ans+=(U[i]-T[i])*(T[i]+U[i]-1)/2ll*F[i];
    	read(C);
    	for(int i=1;i<=n;++i)
    		for(int j=i+1;j<=n;++j)
    			if(G[i][j]=='Y')
    			{
    				ans+=calcu(i,j);
    				merge(i,j);
    			}
    			else e[++ecnt]=edge(i,j,calcu(i,j)+(T[i]+T[j])*C);
    	sort(e+1,e+ecnt+1);
    	for(int i=1;i<=ecnt;++i)
    	{
    		int u=e[i].u,v=e[i].v;
    		ans+=e[i].w*merge(u,v);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    201871010115 马北 《面向对象程序设计(java)》 第67周学习总结
    201871010115马北《面向对象程序设计(java)》第一周学习总结
    《面向对象程序设计(Java)》第四周学习总结
    201871010115——马北《面向对象程序设计JAVA》第二周学习总结
    第十一周作业
    《面向对象程序设计(java)》第十周学习总结
    201871010115 马北 第八周作业
    FPGA开发全攻略——FPGA发展以及赛灵思系列产品
    嵌入式系统词汇表
    FPGA开发全攻略——FPGA内部结构
  • 原文地址:https://www.cnblogs.com/syc233/p/13809933.html
Copyright © 2020-2023  润新知