码迷,mamicode.com
首页 > 其他好文 > 详细

2019-11-9

时间:2019-11-09 17:44:46      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:using   iostream   print   背包   判断   tchar   algorithm   中序遍历   lse   

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\n"):printf("No\n");
    }
    return 0;
}

2019-11-9

标签:using   iostream   print   背包   判断   tchar   algorithm   中序遍历   lse   

原文地址:https://www.cnblogs.com/mendessy/p/11826796.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!