"Ningxia Tournament 2018" and "The 2019 Asia Yinchuan First Round Online Programming"

Question 7 ------------ brother, was beaten up badly (funny) Gangster 13 questions of you half an hour ----------

 

Attendance problems do not write.

 

F :Moving On            (1247ms)

The meaning of problems: given a little right of size N, a complete graph with edge weights, N <200. Q times and then ask each given (u, v, w), allows you to find the shortest path under conditions in addition to other waypoint point right start and end points are <= w's.

Ideas: offline to do so, obviously it needs to sorted. Then think floyd is the shortest path algorithm with a point update. So we floyd the first layer by right point to row a sequence. Then dis [i] [j] k-th layer, it means passing point <= w [k] is shortest. For convenience, all of the points here and ask the right of the w are scattered. (WA competition because there is no initialization for a long time, crying) (online see other people's writing mostly three-dimensional, clearly not necessary, is clearly rolling in the case of offline, the first dimension of no use).

#include<bits/stdc++.h>
#define pii pair<int,int>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=210;
const int maxm=20010;
int mp[maxn][maxn],b[maxn],tot,ans[maxm];
struct in{
    int u,v,w,id;
};
vector<in>G[maxn];
pii a[maxn];
int main()
{
    int T,N,M,C=0;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&M);
        rep(i,1,N) scanf("%d",&a[i].first),a[i].second=i;
        rep(i,1,N) b[i]=a[i].first;
        sort(b+1,b+N+1);
        tot=unique(b+1,b+N+1)-(b+1);
        rep(i,0,tot) G[i].clear();
        rep(i,1,N) a[i].first=lower_bound(b+1,b+tot+1,a[i].first)-b;
        sort(a+1,a+N+1);
        rep(i,1,N) rep(j,1,N) scanf("%d",&mp[i][j]);
        rep(i,1,M) {
            in t;
            scanf("%d%d%d",&t.u,&t.v,&t.w);
            ans[i]=mp[t.u][t.v];
            t.w=upper_bound(b+1,b+tot+1,t.w)-b;
            t.w--; t.id=i;
            G[t.w].push_back(t);
        }
        rep(k,1,N) {
            int tk=k; while(tk+1<=N&&a[tk+1].first==a[k].first) tk++;
            rep(p,k,tk) {
              rep(i,1,N)
               rep(j,1,N){
                 int kk=a[p].second;
                 mp[i][j]=min(mp[i][j],mp[i][kk]+mp[kk][j]);
              }
            }
            for(int i=0;i<G[a[k].first].size();i++){
                in t=G[a[k].first][i];
                ans[t.id]=min(ans[t.id],mp[t.u][t.v]);
            }
            k=tk;
        }
        printf("Case #%d:\n",++C);
        rep(i,1,M) printf("%d\n",ans[i]);
    }
    return 0;
}
View Code

 

G:Factories (1036ms)

Meaning of the questions: Given a size N unrooted tree, let you choose the K leaves, making twenty-two and the shortest distance. (N <1e5, K <100 );

Ideas: such practice could think of to change the root DP, then thought here is not necessary. If there is more than 1 degree, it can be the root, then that is a tree knapsack problem, and who as the root, the effect is the same, so no need to change the root DP. And then I found think O (NK) wording, the pay out of the blind O (NK ^ 2). Actually before. metaphysics.

(NK wording know brother tell me ah)

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=100010;
const ll inf=1LL<<60;
int Laxt[maxn],Next[maxn<<1],To[maxn<<1],len[maxn<<1],cnt;
int ind[maxn],rt,sz[maxn],K;
void add(int u,int v,int w){
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; len[cnt]=w;
}
ll dp[maxn][101],ans;
void read(int &x){
    x=0; char c=getchar();
    while(c>'9'||c<'0') c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
}
void dfs(int u,int f)
{
    sz[u]=0; int leaf=1;  dp[u][0]=0;
    for(int i=Laxt[u];i;i=Next[i]){
        int v=To[i]; if(v==f) continue;
        leaf=0; dfs(v,u);
        for(int k=sz[u];k>=0;k--){
            for(int j=min(K-k,sz[v]);j>=1;j--){
                dp[u][k+j]=min(dp[u][k+j],dp[u][k]+dp[v][j]+1LL*(K-j)*j*len[i]);
            }
        }
        sz[u]+=sz[v];
    }
    if(leaf) sz[u]=1,dp[u][1]=0;
    if(sz[u]>=K) ans=min(ans,dp[u][K]);
}
int main()
{
    int T,N,C=0,u,v,w;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&K);
        rep(i,1,N) Laxt[i]=0; cnt=0;
        rep(i,0,N+1) rep(j,0,K) dp[i][j]=inf; ans=inf;
        rep(i,1,N) ind[i]=0;
        rep(i,1,N-1){
            read(u); read(v); read(w);
            add(u,v,w); add(v,u,w);
            ind[u]++; ind[v]++;
        }
        if(N==1||K<=1) ans=0;
        else if(N==2) ans=len[1];
        else {
            rep(i,1,N) if(ind[i]>1) {
                rt=i; break;
            }
            dfs(rt,0);
        }
        printf("Case #%d: %lld\n",++C,ans);
    }
    return 0;
}
View Code

 

K:Vertex Covers (1060ms)

The meaning of problems: given M N-point no edge to FIG each point a little right. Coverage point represents a point set S {} covers all sides, which is the product of the contribution of the right point of S. Now let's all you seek sum of the contributions. N <36, to ensure that no edge weight, loopback.

Ideas: point coverage problem, and N is relatively small, difficult to think like pressure. Where N can be a maximum of 36, obviously you need a binary enumeration, and then find a way to merge two sides.

So we put points into L, R two sets. Then the edge has three categories: 1, end points in L; 2, point ends in R; 3, two ends of each one of the L and R.

Clearly then, for Class 1 side, to at least one selected from the two endpoints; class 2 for the same reason the edge; for Class 3 side, if L is not selected, then R is mandatory, i.e. set up a superset, and super we can use high-dimensional set and get prefixes. So this question would be finished. (100ms those who ran out of all the gods, right)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2000010;
int a[maxn],sum[maxn],ltl[40],ltr[40],rtr[40],Mod;
void MOD(int &x){ if(x>=Mod) x-=Mod;}
int main()
{
    int T,N,M,u,v,C=0;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&N,&M,&Mod);
        rep(i,0,N-1) scanf("%d",&a[i]);
        rep(i,0,N-1) ltl[i]=ltr[i]=rtr[i]=0;
        int L=(N+1)/2, R=N-L, ans=0;
        rep(i,1,M){
            scanf("%d%d",&u,&v);
            u--, v--;
            if(u>v) swap(u,v);
            if(u<L){
                if(v<L) ltl[u]|=(1<<v);
                else ltr[u]|=(1<<(v-L));
            }
            else rtr[u]|=(1<<(v-L));
        }
        rep(i,0,(1<<R)-1){
            int res=1;
            rep(j,0,R-1){
                if(i&(1<<j)) res=1LL*res*a[j+L]%Mod;
                else {
                    res=res*((rtr[j+L]|i)==i);
                    if(!res) break;
                }
            }
            sum[i]=res;
        }
        rep(i,0,R-1) {
            rep(j,0,(1<<R)-1) {
                if(!(j&(1<<i))) MOD(sum[j]+=sum[j|(1<<i)]);
            }
        }
        rep(i,0,(1<<L)-1){
            int res=1,need=0;
            rep(j,0,L-1) {
                if(i&(1<<j)) res=1LL*res*a[j]%Mod;
                else {
                    res=res*((ltl[j]|i)==i),need|=ltr[j];
                    if(!res) break;
                }
            }
            MOD(ans+=1LL*res*sum[need]%Mod);
        }
        printf("Case #%d: %d\n",++C,ans);
    }
    return 0;
}
View Code

 

L:Continuous Intervals

The meaning of problems: given a sequence of length N, the number of subintervals seeking after ordering satisfies this range, the number of adjacent phase difference <= 1;

Idea: That is asked how many intervals satisfy the max-min + 1 == cnt, max and min are the maximum and minimum range, cnt is the number of kinds of intervals. 

Divide and conquer it? Not divided, no rule of law. Heuristic partition it? I can not find mid. 

So try violence? We enumerate the right point R, then L is the number of legitimate statistics. Hypothesis is [1, R-1] is all of the information, is now added into a R,

1, may have some impact on extreme value range; 2, may have an impact on a range of cnt. 

We only need to maintain good information about each point of L, the suffix used to represent the extremes and cnt can be.  

      How to maintain the range extremes: tree line.

      How to reduce maintenance times: monotony queue + lazy.

      For cnt: Effect only [laxt [a [R]] + 1, R] of this interval.

In summary therefore, only you need to maintain three lazy to. Then the right R, modified segment tree, the statistics of how many max-min + 1 = cnt, i.e. max-min-cnt == - 1 to the section.

 

Guess you like

Origin www.cnblogs.com/hua-dong/p/11441373.html