Educational Codeforces Round 104 (Rated for Div. 2) E. Cheap Dinner (line segment tree optimization dp)

Title:

Have n 1 n_1n1Kinds of staple food, n 2 n_2n2Non- staple food, n 3 n_3n3Kinds of drinks, n 4 n_4n4Kinds of desserts, there are m 1, m 2, m 3 m_1,m_2,m_3m1,m2,m3Pair relationship, m 1 m_1m1Each pair of relations in represents that some staple foods cannot be matched with non-staple foods, m 2 m_2m2It means that some non-staple foods and beverages cannot be matched, m 3 m_3m3It means that some beverages and desserts cannot be matched. Each food has a price. Ask how to choose to make the price the least, and these 4 4There are 4 types, and the output is the least expensive.

answer:

At first I thought about the cost flow, but when I saw that the data was too large, I gave up decisively. Later, I thought of using the line segment tree to maintain it, but the complexity was wrong. I thought it was a fake algorithm. Then I thought about it and it was actually possible.

d p [ i ] [ j ] dp[i][j] d p [ i ] [ j ] means pre-selectioniiFood category i ,iii type food selectionjjThe minimum cost of j , the data is smaller, in fact, it is easy to think of how to transfer:

d p [ i ] [ j ] = min ⁡ k = 1 n [ i − 1 ] d p [ i − 1 ] [ k ] + c o s t [ i ] [ j ] dp[i][j]=\min\limits_{k=1}^{n[i-1]} dp[i-1][k]+cost[i][j] dp[i][j]=k=1minn[i1]dp[i1][k]+cost[i][j]

The larger the data is to use the line segment tree to maintain the minimum value of the interval. Because there are foods that cannot be matched, you only need to sort the foods that cannot be matched, and then evaluate the interval. At first I thought the complexity here was O (nmlogn) O(nmlogn)O ( n m l o g n ) , actuallyO (mlogn) O(mlogn)O ( m l o g n )

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=2e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int n[5];
int a[5][MAXN];
int dp[MAXN];
vector<int>g[MAXN];
struct Node
{
    
    
    int l,r;
    int minn;
}node[5][MAXN<<2];
void build(int id,int l,int r,int num)
{
    
    
    node[id][num].l=l;
    node[id][num].r=r;
    if(l==r)
    {
    
    
        node[id][num].minn=dp[l];
        return;
    }
    int mid=(l+r)>>1;
    build(id,l,mid,num<<1);
    build(id,mid+1,r,num<<1|1);
    node[id][num].minn=min(node[id][num<<1].minn,node[id][num<<1|1].minn);
}
int query(int id,int l,int r,int num)
{
    
    
    if(node[id][num].l>=l&&node[id][num].r<=r)
    {
    
    
        return node[id][num].minn;
    }
    int mid=(node[id][num].l+node[id][num].r)>>1;
    int ans=1e9;
    if(l<=mid)
    {
    
    
        ans=min(ans,query(id,l,r,num<<1));
    }
    if(r>mid)
    {
    
    
        ans=min(ans,query(id,l,r,num<<1|1));
    }
    return ans;
}
void updata(int id,int pos,int val,int num)
{
    
    
    if(node[id][num].l==node[id][num].r)
    {
    
    
        node[id][num].minn=val;
        return ;
    }
    int mid=(node[id][num].l+node[id][num].r)>>1;
    if(pos<=mid)
    {
    
    
        updata(id,pos,val,num<<1);
    }
    else updata(id,pos,val,num<<1|1);
    node[id][num].minn=min(node[id][num<<1].minn,node[id][num<<1|1].minn);
}
int main()
{
    
    
    for(int i=1;i<=4;i++)
    {
    
    
        scanf("%d",&n[i]);
    }
    for(int i=1;i<=4;i++)
    {
    
    
        for(int j=1;j<=n[i];j++)
        {
    
    
            scanf("%d",&a[i][j]);
            if(i==1) dp[j]=a[i][j];
            else dp[j]=1e9;
        }
        build(i,1,n[i],1);
    }
    for(int i=2;i<=4;i++)
    {
    
    
        for(int j=0;j<=n[i];j++) g[j].clear();
        int m;scanf("%d",&m);
        for(int j=1;j<=m;j++)
        {
    
    
            int x,y;scanf("%d%d",&x,&y);
            g[y].push_back(x);
        }
        for(int j=1;j<=n[i];j++)
        {
    
    
            if(g[j].size()==0)
            {
    
    
                int minn=query(i-1,1,n[i-1],1);
                if(minn==1e9) continue;
                updata(i,j,minn+a[i][j],1);
            }
            else
            {
    
    
                sort(g[j].begin(),g[j].end());
                g[j].push_back(n[i-1]+1);
                int pre=1;
                int minn=1e9;
                for(int k=0;k<g[j].size();k++)
                {
    
    
                    if(g[j][k]-1>=pre) minn=min(minn,query(i-1,pre,g[j][k]-1,1));
                    pre=g[j][k]+1;
                }
                if(minn!=1e9) updata(i,j,minn+a[i][j],1);
            }
        }
    }
    int ans=query(4,1,n[4],1);
    if(ans==1e9) printf("-1\n");
    else printf("%d\n",ans);
}

Guess you like

Origin blog.csdn.net/weixin_45755679/article/details/114006064