Three questions

Or put it in order of increasing difficulty.

T1 https://www.luogu.com.cn/problem/P3360

Since the order it gives is a dfs order, then reading directly while dfs is finished, because it has both volume and value, so it is enough to enumerate how much time is allocated to each corridor, which is a backpack problem on a tree.

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=600;
ll dp[N][N],v;
int n,w,cnt;
void dfs(int u){
    int t,x;
    scanf("%d%d",&t,&x);
    t<<=1;
    if(x){
        for(int i=1;i<=x;i++){
            scanf("%lld%d",&v,&w);
            for(int j=n;j>=t+w;j--){
                dp[u][j]=max(dp[u][j],dp[u][j-w]+v);
            }
        }
        return ;
    }
    int l=++cnt;dfs(l);
    int r=++cnt;dfs(r);
    for(int i=t;i<=n;i++)
        for(int j=0;i>=j+t;j++)
            dp[u][i]=max(dp[u][i],dp[l][j]+dp[r][i-j-t]);
}
int main(){
    scanf("%d",&n);
    n--;
    cnt=1;
    dfs(1);
    printf("%lld\n",dp[1][n]);
}

T2 https://www.luogu.com.cn/problem/P4303

This question is actually quite naked. If you don't look at the data range, just run an LCS. But its data range is very large, so you should consider the NlogN writing method of LCS. It is obviously not possible to directly set the board, because there are repetitions, and the number of repetitions is the same. The length of the LCS is updated, so I record these 5 positions and write them according to the NlogN method, and then enumerate and try to update the answers one by one. But there is a problem, if the five positions are 1, 2, 3, 4, 5 in turn, then this may be updated by one update, is it not over? So to prevent this from happening, you need to enumerate backwards.

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int w,n;
int tr[N];
int lowbit(int i){
    return i&-i;
}
void updata(int x,int val){
    while(x<=n){
        tr[x]=max(tr[x],val);
        x+=lowbit(x);
    }
}
int find(int x){
    int res=0;
    while(x){
        res=max(res,tr[x]);
        x-=lowbit(x);
    }
    return res;
}
int main(){
    vector<int > pos[N];
    scanf("%d",&n);
    n*=5;
    for(int i=1;i<=n;i++){
        scanf("%d",&w);
        pos[w].push_back(i);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&w);
        for(int j=pos[w].size()-1;j>=0;j--)
            updata(pos[w][j],find(pos[w][j]-1)+1);
    }
    printf("%d\n",find(n));
}

T3


At first glance, this question is clueless, except of course for the watch. So you can only watch.
The first thing I found in the watch is that the answer to the first question was n-2 and some special judgments, so printf n-2, 20 points.
I didn't want to prove it at that time, but now I have to prove it.
The case where the maximum number of solutions is n obviously does not exist, and it will definitely be included. What about n-1? The scheme of 1 must be n and the union of n-1 should be n, and the scheme of 2 should not contain 1, so how can this 2 scheme be generated, is it, so it can only be n-2.
In fact, this proof is not very rigorous, but just understand it.
So let's consider generating these n-2 schemes. The table is definitely able to be printed, but when it's played ............... No, then there is no way to easily make a scheme What about generating another solution? For example, the following:
\ (x_1 \)
\ (x_2 \) \ (x_3 \)
\ (x_3 \) \ (x_4 \) \ (x_5 \)
Considering how the following scheme can be obtained, obviously I can Add a number to the back, and then push each line backwards, the first line is vacant, and another number is enough. Put 1 to n-2 on the last line, the generation is completed, so this question becomes a magical simulation question, and then hit A. . . . .
There is still a problem, this generation method can only be pushed from n-2 to n, so it is necessary to consider whether the given number is odd or even.

#include<cstdio>
using namespace std;
const int N=1e3+10;
int num[N][N];
int main(){
//    freopen("course.in","r",stdin);
//    freopen("course.out","w",stdout);
    int n;
    scanf("%d",&n);
    if(n==1||n==2){
        printf("1\n1 1");
    }
    else if(n==3){
        printf("2\n1 1\n2 2 3");
    }
    else {
        printf("%d\n",n-2);
        num[1][1]=1;num[2][1]=2;num[2][2]=3;
        if(n&1){
            for(int i=5;i<=n;i+=2){
                for(int j=1;j<=i-4;j++)
                    num[j][j+1]=i;
                for(int j=i-4;j>=1;j--)
                    for(int k=1;k<=j+1;k++)
                        num[j+1][k]=num[j][k];
                num[1][1]=i-1;
                for(int j=1;j<=i-2;j++)
                    num[i-2][j]=j;
            }
            for(int i=1;i<=n-2;i++){
                printf("%d ",i);
                for(int j=1;j<=i;j++)printf("%d ",num[i][j]);
                printf("\n");
            }
        }
        else{
            for(int i=6;i<=n;i+=2){
                for(int j=1;j<=i-4;j++)
                    num[j][j+1]=i;
                for(int j=i-4;j>=1;j--)
                    for(int k=1;k<=j+1;k++)
                        num[j+1][k]=num[j][k];
                num[1][1]=i-1;
                for(int j=1;j<=i-2;j++)
                    num[i-2][j]=j;
            }
            for(int i=1;i<=n-2;i++){
                printf("%d ",i);
                for(int j=1;j<=i;j++)printf("%d ",num[i][j]);
                printf("\n");
            }
        }
        /*else if(n==4){
            printf("2\n1 1\n2 2 3");
        }
        else if(n==6){
            printf("4\n1 1\n2 2 3\n3 2 4 5\n4 4 5 6");
        }*/
    }
}

Guess you like

Origin www.cnblogs.com/anyixing-fly/p/12755411.html