2019 Niuke summer multi school training camp (the second)

Keywords: PHP

Title gate

Title number A B C D E F G H I J
state . . . Ø . Ο . Ο . .

D.Kth Minimum Clique

The undirected graph of n points is given. Each point has a weight. What is the weight of the smallest clique?

Idea: put all the individual points into the priority queue, take out the points at the top of the heap every time, such as external expansion, and the group leaving the queue for the k time is the k small group.

Use "int128" to record various states.

Don't write multiple groups of data (don't empty the last priority queue)

#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=110;
struct node{
    ll w;
    int id;
    __int128 status;
    friend bool operator<(const node &a,const node &b){
        return a.w>b.w;
    }
};
priority_queue<node >q;
int n,k;
ll val[maxn];
char s[maxn][maxn];
__int128 out[maxn];
int main(){
    while(cin>>n>>k){
        clr(out,0);
        for(int i=0;i<n;i++){
            scanf("%lld",&val[i]);
        }
        for(int i=0;i<n;i++){
            scanf("%s",s[i]);
            for(int j=0;j<n;j++){
                int ty=s[i][j]-'0';
                out[i]=out[i]+(__int128(ty)<<j);
            }
        }
        for(int i=0;i<n;i++){
             q.push({val[i],i,__int128(1)<<i});
        }
        k--;
        if(k==0){
            puts("0");
            continue;
        }
        ll ans=-1;
        while(!q.empty()){
            node st=q.top();
            q.pop();
            k--;
            if(k==0){
                ans=st.w;
                break;
            }
            for(int i=st.id+1;i<n;i++){
                if((out[i]&st.status)==st.status){
                    q.push({st.w+val[i],i,st.status|(__int128(1)<<i)});
                }
            }
        }
        printf("%lld\n",ans);
//        while(!q.empty())q.pop();
    }
}

F.Partition problem

Give 2n people, divided into two teams, give two people if not in the same team, ask for the maximum income.

 

Train of thought: the solution seems to be a search. Teammates are stuck in the game.

The search method is to simulate two arrays. A point is either put into a or b. when it is put in, the value is accumulated directly and dfs is carried out. The time complexity is C (28,14) * 28.

 

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=b;i>=a;--i)
using namespace std;
#define ll long long
const int N=35;
struct node{
    short int a[29];
    int w;
    ll ans=0;
}p[20];
int a[N][N],c[N],flag[N],col[N],n;
ll ans=0,an=0;
ll rd()
{
    ll 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;
}
void init()
{
    memset(p[1].a,-1,sizeof(p[1].a));
    rep(i,1,n) p[1].a[i]=1;
    p[1].w=n;
    rep(i,1,n)
    {
        c[i]=i;
        col[i]=0;
    }
    rep(i,1,n)
        rep(j,n+1,2*n)
            ans=ans+a[i][j];
    p[1].ans=ans;
    an=ans;
}
inline ll solve(int x,int id)
{  
    ll ans=0;
    int k=n<<1;
    rep(i,1,k)
    {
        ans=ans+(-a[i][x]+a[i][p[id].w])*p[id].a[i];
    }
    ans=p[id].ans+ans+(a[x][p[id].w]<<1); an=max(an,ans);
    return ans;
}
int main()
{
    n=rd();
    rep(i,1,2*n)
        rep(j,1,2*n)
            a[i][j]=rd();
    init();
    int pos=n,TIME=0;
    while(c[1]<=n)
    {
        while( c[pos]>=n+pos ) pos--;
        c[pos]++;
        rep(j,pos+1,n) c[j]=c[j-1]+1;
        if(pos<n)
        {
            ll x=solve(c[pos],n-pos+1);
            if(col[pos]==0)
            {
                col[pos]=1;
                memset(p[n-pos+2].a,-1,sizeof(p[n-pos+2].a));
                rep(j,1,n) p[n-pos+2].a[c[j]]=1;
                p[n-pos+2].w=c[pos-1];
                p[n-pos+2].ans=x;
            }  
            rep(j,pos+1,n) col[j]=0;
            memset(p[1].a,-1,sizeof(p[1].a));
            rep(j,1,n) p[1].a[c[j]]=1;
            p[1].w=c[n];
            p[1].ans=x;
        }
        else{
            ll x=solve(c[pos],1);
            if(col[pos]==0)
            {
                col[pos]=1;
                memset(p[n-pos+2].a,-1,sizeof(p[n-pos+2].a));
                rep(j,1,n) p[n-pos+2].a[c[j]]=1;
                p[n-pos+2].w=c[pos-1];
                p[n-pos+2].ans=x;
            }
        }
        pos=n;
    }
    printf("%lld\n",an);
}

 H.Second Large Rectangle

Problem meaning: given 01 matrix, 1 is something, find the second largest submatrix area.

Idea: in fact, the monotone stack deals with the largest submatrix, adding a little change in the process.

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=b;i>=a;i--)
using namespace std;
#define ll long long
const int N=3e5+5;
const int mod = 998244353;
int ans=0,ans1=0,n,m,p;
char ss[1010];
int a[1010][1010],b[1010],s[1010],w[1010];
int sum(int a, int b) {
    int s = (a + b);
    if (s >= mod) s -= mod;
    return s;
}
int sub(int a, int b) {
    int s = a - b;
    if (s < 0) s += mod;
    return s;
}
int mult(int a, int b) {
    return (1LL * a * b) % mod;
}
ll rd()
{
    ll 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 main()
{
    n=rd();m=rd();
    rep(i,1,n)
    {
        scanf("%s",ss+1);
        rep(j,1,m) if(ss[j]!='0') a[i][j]=ss[j]-'0'+a[i-1][j];
                    else a[i][j]=0;
    }
    rep(i,1,n)
    {
        rep(j,1,m)
        {
            b[j]=a[i][j];
            //printf("%d\n",b[j]);
            }
        b[m+1]=0;
        int p=0;
        rep(j,1,m+1)
        {
            if(b[j]>s[p])
            {
                s[++p]=b[j],w[p]=1;
            }
            else{
                int width=0;
                while(s[p]>b[j])
                {
                    width+=w[p];
                    if(width*s[p]>ans)
                    {
                        //printf("i=%d j=%d %d %d\n",i,j,ans1,ans);
                        ans1=max(ans,(width-1)*s[p]);
                        ans=width*s[p];
                    }
                    else if(width*s[p]>ans1) ans1=max(ans1,width*s[p]);
                    p--;
                }
                s[++p]=b[j];w[p]=width+1;
            }
        }
    }
    printf("%d\n",ans1);
}

Posted by techite on Sun, 20 Oct 2019 08:31:49 -0700