• 2019-11-9


    T1

    显然,对于一个城堡,要么就不放兵,要么就放到(2*a_i+1)

    然后对于一个城堡,我们首先将对手放兵从小到大排序,然后就是一个分组背包(每一组只能选1个)的问题了QAQ 复杂度(O(nms)) 因为跑不满上界,所以过得了。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    const int maxn=1100;
    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;
    }
    int s,n,m;
    int f[maxn][20010];
    int dp[20010],qaq[maxn];
    int arr[maxn][maxn],arrr[maxn][maxn],val[maxn][maxn];
    int main(){
    	freopen("arrange.in","r",stdin);
    	freopen("arrange.out","w",stdout);
    	s=read();n=read();m=read();
    	for(int i=1;i<=s;i++)
    		for(int j=1,x;j<=n;j++)
    			x=read(),arr[i][j]=x*2+1;
    	if(s==1){
    		for(int i=1;i<=n;i++){
    			for(int j=0;j<=m;j++)
    				f[i][j]=f[i-1][j];
    			for(int j=arr[1][i];j<=m;j++){
    				f[i][j]=max(f[i][j],f[i-1][j-arr[1][i]]+i);
    			}
    		}	
    		printf("%d",f[n][m]);
    	}
    	else{
    		memset(dp,0xcf,sizeof(dp));
    		dp[0]=0;
    		for(int i=1;i<=s;i++)
    			for(int j=1;j<=n;j++)
    				arrr[j][i]=arr[i][j];
    		for(int i=1;i<=n;i++)
    			sort(arrr[i]+1,arrr[i]+1+s);
    		for(int i=1;i<=n;i++){
    			for(int j=m;j>=0;j--){
    				for(int k=1;k<=s;k++){
    					if(j>=arrr[i][k])
    						dp[j]=max(dp[j],dp[j-arrr[i][k]]+(i)*(k));
    				}
    			}
    		}
    
    		int ans=0;
    		for(int i=0;i<=m;i++) ans=max(ans,dp[i]);
    		printf("%d",ans);
    	}
    	return 0;
    }
    

    T2

    这道题通过题目可以分析出来:父亲与其所有的后代权值的差绝对值(le k) 。我们考虑先找一个根节点:显然根节点与除了自己的所有节点的权值差绝对值(le k) 找到根节点之后,我们把根节点抛开不管,显然根节点的左子树在中序遍历中一定在根节点的左边,右子树在中序遍历中一定在根节点的右边,然后将根节点的左子树,右子树(看做独立的树) 进行同样的操作,最后就可以构成符合条件的树,如何不能构成,就返回(false)

    如何做思路就很明了了

    (solve(l,r)) 表示当前处理到中序遍历的([l,r])了,然后在这个区间从左向右扫一遍,找到一个满足条件的(i)使得(a[i]+k>=maxx && a[i]-k<=maxx) 然后继续递归(solve(l,i-1),solve(i+1,r))

    但是显然这样做肯定是(O(n^2))的 过不了。 然而玄学的启发式合并可以将这道题的复杂度转换为(O(nlogn)),我不会证。 启发式合并就是从当前枚举的左右区间同时向中间扫 即在第i步的时候判断(l+i,r-i) 对应的数是否是满足条件的。如果满足条件就可以直接递归下去。 至于为什么启发式合并要快一点,因为同时从左边,右边向中间扫,而如果扫到了就可以直接递归下去。相当于可以通过一个小的区间,确定一个大的区间,复杂度自然就下去了

    还有就是注意ST表维护区间最大最小值的细节QAQ

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    const int maxn=2e5+10;
    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;
    }
    int t,n,k,a[maxn],lg[maxn],stmin[30][maxn],stmax[30][maxn];
    int getmin(int l,int r){
    	int k=lg[r-l+1];
    	return min(stmin[k][l],stmin[k][r-(1<<k)+1]);
    }
    int getmax(int l,int r){
    	int k=lg[r-l+1];
    	return max(stmax[k][l],stmax[k][r-(1<<k)+1]);
    }
    bool solve(int l,int r){
    	if(l>=r) return true;
    	int minn=getmin(l,r),maxx=getmax(l,r);
    	int i=0;
    	for(;i+l<=r-i;i++){
    		if(a[i+l]-k<=minn && a[i+l]+k>=maxx){
    			return solve(l,l+i-1) && solve(l+i+1,r);
    		}
    		if(a[r-i]-k<=minn && a[r-i]+k>=maxx){
    			return solve(l,r-i-1) && solve(r-i+1,r);
    		}
    	}
    	return false;
    }
    int main(){
    	freopen("tree2.in","r",stdin);
    	freopen("tree.out","w",stdout);
    	t=read();
    	while(t--){
    		n=read();k=read();
    		lg[0]=-1;
    		for(int i=1;i<=n;i++){
    			a[i]=read();
    			lg[i]=lg[i>>1]+1;
    			stmin[0][i]=a[i];stmax[0][i]=a[i];
    		}
    		for(int i=1;i<=lg[n];i++)
    			for(int j=1;j+(1<<i)-1<=n;j++){
    				stmin[i][j]=min(stmin[i-1][j],stmin[i-1][j+(1<<(i-1))]);
    				stmax[i][j]=max(stmax[i-1][j],stmax[i-1][j+(1<<(i-1))]);
    			}
    		solve(1,n)?printf("Yes
    "):printf("No
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    Git配置SSH访问GitHub
    vue 관련
    node
    关于CheckBox和EditText在ListView里多布局的处理
    百度地图定位
    java常用简单正则表达式写法
    Android二维码开源项目zxing编译
    Andrew XUtils的session获得和cookieStore使用
    常用易忘知识点
    替换Fragment 报错 The specified child already has a parent. You must call removeView()
  • 原文地址:https://www.cnblogs.com/mendessy/p/11826796.html
Copyright © 2020-2023  润新知