首页 > 代码库 > 2017.8.12 联考题

2017.8.12 联考题

今天的题比(wo)较(zhi)水(zhang),好几个大佬都AK了......
第一题
题意
给1~n的板子,按一定顺序排放,板子围起来的地方可以盛水,问给定n和要盛的水x,输出合法序列
n<=1e6 x<=1e13
solution 先把n放在最左边,把n-1放在n后面,在他俩中间加数 设当前要加的高度是H,那它对总水的贡献是 (n-1-H) 一直加到当前水==x,再把没加的从大到小加在n-1后面 如果加完都没有加满水,就 -1 (根据数学归(wo)纳(bu)法(hui))
技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define ll long long
 5 using namespace std;
 6 
 7 int n;
 8 ll sum;
 9 int a[1000066],cnt,flag[1000066];
10 
11 int main(){
12     
13     //freopen("1.txt","r",stdin);
14     //freopen("2.txt","w",stdout);
15     
16     scanf("%d%lld",&n,&sum);
17     
18     if(n<3)
19     {
20         if(sum!=0)
21         {
22             printf("-1");
23             return 0;
24         }
25         else
26         {
27             for(int i=1;i<=n;++i)
28               printf("%d ",i);
29             return 0;
30         }
31     }
32     
33     a[++cnt]=n;flag[n]=1;
34     for(int i=1;i<=n-2;++i)
35     {
36         if(sum==0)
37           break;
38         if((n-1-i)<=sum)
39         {
40             a[++cnt]=i;
41             flag[i]=1;
42             sum-=(n-1-i);
43         }
44     }
45     if(sum!=0)
46       printf("-1");
47     else
48     {
49         a[++cnt]=n-1;
50         flag[n-1]=1;
51         for(int i=n;i>=1;--i)
52           if(!flag[i])
53             a[++cnt]=i;
54         for(int i=1;i<=cnt;++i)
55           printf("%d ",a[i]);
56     }
57     
58     //while(1);
59     return 0;
60 }
61     
第一题
第二题:
题意
给一个长度为n的序列,求其长度为k的子序列max值的和,mod1e7
n<=1e5 k<=50 solution
先把值排个序 从小到大枚举序列max 它对答案的贡献是 v[i]*C(i-1,k-1)
组合数直接递推:c[n][m]=c[n-1][m]+c[n-1][m-1]
技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define ll long long
 6 #define mem(a,b) memset(a,b,sizeof(a))
 7 using namespace std;
 8 const int N=100066;
 9 const int mod=1000000007;
10 
11 int n,k;
12 ll a[N];
13 ll c[N][56];
14 ll ans;
15 
16 void chu()
17 {
18     c[0][0]=1;
19     for(int i=1;i<=k;++i)
20         c[i][i]=1;
21     for(int i=1;i<N;++i)
22       c[i][0]=1;
23     
24     for(int i=2;i<=k;++i)
25       for(int j=1;j<i;++j)
26         c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
27     for(int i=k+1;i<N;++i)
28       for(int j=1;j<=k;++j)
29         c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
30     
31 /*    printf("\n");
32     for(int i=1;i<=5;++i)
33     {
34         for(int j=0;j<=i;++j)
35           printf("%lld ",c[i][j]);
36         printf("\n");
37     }
38     printf("\n");*/
39 }
40 
41 int main(){
42     
43     //freopen("1.txt","r",stdin);
44     
45     scanf("%d%d",&n,&k);
46     
47     //printf("k=%d\n",k);
48     
49     chu();
50     
51 /*    for(int i=40;i<=45;++i)
52       printf("%lld\n",c[5555][i]);*/
53     
54     for(int i=1;i<=n;++i)
55       scanf("%lld",&a[i]);
56     
57     sort(a+1,a+1+n);
58     
59     for(int i=k;i<=n;++i)
60         ans=(ans+a[i]*c[i-1][k-1]%mod)%mod;
61     
62     cout<<ans;
63     //while(1);
64     return 0;
65 }
第二题
第三题:
题意
给一个二叉树,修改其中一些节点的值,使其满足二叉搜索树的性质,特别的左右子树的值不能和当前节点值相等
n<=1e5
solution
先对整棵树进行中序遍历得到一个序列 (这么简单我竟然2个小时都没有想出来......)
然后问题变成了 求这个序列的最长上升子序列 设序列为f[i]
j>i f[j]>d[i]
由于不能相等 所以满足 f[j]-f[i]>=j-i 即 f[j]-j>=f[i]-i
设 g[i]=f[i]-i
问题有转换为求 g[i] 的最长不下降子序列
这个比较好求,直接离散g[i] 树状数组维护即可
技术分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define p(x) a[x].p
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
using namespace std;
const int INF=0x7fffffff;
const int N=100066;

int c[N];
void add(int pos,int val)
{
    for(int i=pos;i<N;i+=(i&(-i)) )
      if(c[i]<val)
        c[i]=val;
}
int qq(int pos)
{
    int ans=-INF;
    for(int i=pos;i>0;i-=(i&(-i)) )
      if(ans<c[i])
        ans=c[i];
    return ans;
}

struct son
{
    int ch[2],p;
};
son a[N];

int n,u,o,sum;
int f[N],cnt,v[N],h[N];
int g[N];

void dfs(int x)
{
    if(x==-1)
      return ;
    dfs(ls(x));
    h[++cnt]=v[x];
    dfs(rs(x));
}

struct son1
{
    int pos,val;
    friend bool operator < (son1 a,son1 b)
    {
        return a.val<b.val;
    }
};
son1 li[N];

int now;

void lisan()
{
    for(int i=1;i<=n;++i)
    {
        li[i].val=g[i];
        li[i].pos=i;
    }
    sort(li+1,li+1+n);
    li[0].val=-INF;
    for(int i=1;i<=n;++i)
    {
        if(li[i].val==li[i-1].val)
          g[li[i].pos]=now;
        else
          g[li[i].pos]=++now;
    }
}

int main(){
    
    mem(a,-1);
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      scanf("%d",&v[i]);
    for(int i=2;i<=n;++i)
    {
        scanf("%d%d",&u,&o);
        p(i)=u;
        a[u].ch[o]=i;
    }
    
    dfs(1);
    
    for(int i=1;i<=n;++i)
      g[i]=h[i]-i;
    
    lisan();
    
    for(int i=1;i<=n;++i)
    {
        f[i]=qq(g[i])+1;
        add(g[i],f[i]);
        if(sum<f[i])
          sum=f[i];
    }
    cout<<(n-sum);
    
    //while(1);
    return 0;
}
    
第三题

2017.8.12 联考题