首页 > 其他分享 >Solution -「JOISC 2020」建筑装饰 4

Solution -「JOISC 2020」建筑装饰 4

时间:2023-09-28 15:44:22浏览次数:34  
标签:cnt chkmax int Solution JOISC 2020 && 100 dp

  朴素的 DP 形式是定义 \(f_{i, j, A/B}\) 表示前 \(i\) 个元素选择了 \(j\) 个 \(A\) 的可达性. \(\mathcal O(n^2)\). 交换状态与值域, 定义 \(f_{i, A/B, A/B}\) 表示前 \(i\) 个元素中的最后一个元素 (即 \(i\)) 选择了 \(A/B\), 在最大化 \(A/B\) 的数量的目标下求得的 \(A/B\) 的数量.

  转移在代码注释里, 答案倒着构造.

/**
 * dp[i][A/B][A/B]: 前 i 个, 第 i 个选 A 还是 B, 最大化 A/B 的数量
 * a[i] >= a[i-1]: dp[i-1][A][A]+1 -> dp[i][A][A]; dp[i-1][A][B] -> dp[i][A][B]
 * a[i] >= b[i-1]: dp[i-1][B][A]+1 -> dp[i][A][A]; dp[i-1][B][B] -> dp[i][A][B]
 * b[i] >= a[i-1]: dp[i-1][A][B]+1 -> dp[i][B][B]; dp[i-1][A][A] -> dp[i][B][A]
 * b[i] >= b[i-1]: dp[i-1][B][B]+1 -> dp[i][B][B]; dp[i-1][B][A] -> dp[i][B][A]
*/
enum Element {A, B};
const int N = 1e6;
int n, a[N + 100], b[N + 100], f[N + 100][2][2];
char ans[N + 100];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(nullptr);
    rd(n), rds(a, 2 * n) , rds(b, 2 * n);
    rep (i, 1, 2 * n) {
        if (a[i] >= a[i - 1]) {
            chkmax(f[i][A][A], f[i - 1][A][A] + 1);
            chkmax(f[i][A][B], f[i - 1][A][B]);
        }
        if (a[i] >= b[i - 1]) {
            chkmax(f[i][A][A], f[i - 1][B][A] + 1);
            chkmax(f[i][A][B], f[i - 1][B][B]);
        }
        if (b[i] >= a[i - 1]) {
            chkmax(f[i][B][B], f[i - 1][A][B] + 1);
            chkmax(f[i][B][A], f[i - 1][A][A]);
        }
        if (b[i] >= b[i - 1]) {
            chkmax(f[i][B][B], f[i - 1][B][B] + 1);
            chkmax(f[i][B][A], f[i - 1][B][A]);
        }
    }
    int cnt[2] = {}, last = 1e9;
    drep (i, 2 * n, 1) {
        if (cnt[A] + f[i][A][A] >= n && cnt[B] + f[i][A][B] >= n && a[i] <= last) last = a[i], ans[i] = 'A', cnt[A]++;
        else if (cnt[A] + f[i][B][A] >= n && cnt[B] + f[i][B][B] >= n && b[i] <= last) last = b[i], ans[i] = 'B', cnt[B]++;
        else {
            cout << "-1\n"; return 0;
        }
    }
    copy_n(ans + 1, 2 * n, ostream_iterator<char>(cout, ""));
}

标签:cnt,chkmax,int,Solution,JOISC,2020,&&,100,dp
From: https://www.cnblogs.com/orchid-any/p/17735945.html

相关文章

  • Solution of 洛谷-P1896
    并不会有更好的阅读体验\(\text{Sol}\)我们先看一眼数据范围:\(1\leN\le9\)没关系,DFS会出手。好吧,正经的说,如果暴搜的话复杂度会涨到\(\textO(2^{n^2})\),\(\textT\)到飞起。此时我们发现有个东西叫状压\(\text{DP}\),也是解决小范围数据的问题。老套路,枚举每一行,......
  • Solution -「模拟赛」草莓蛋糕
      \(\max(a_x+a_y,b_y+b_x)\)的贡献形式不是独立的,并不好进行分析。考虑通过分类讨论将\(\max\)拆开。若令\(h_i=a_i-b_i\),\(h'_i=b_i-a_i\),可以发现若\(h_x\geqslanth'_y\)取值则为\(b_x+b_y\),反之亦然。  注意到\(h\)本身自带一个一维偏序关系,于......
  • JOISC 2019
    試験/Examination直接三维偏序。#include<iostream>#include<cstdio>#include<cstring>#include<numeric>#include<algorithm>usingnamespacestd;constintN=100005;intn,Q;intv[N*6],cnt;structQuery{inta,b,c;intv,i......
  • JOISC 2020
    ビルの飾り付け4/Building4令\(f_{i,0/1,j}\)表示到第\(i\)位,第\(i\)位选的是\(A_i/B_i\),\(1\simi\)选了\(j\)个\(A_i\)是否合法。可以发现,对于一个\(f_{i,0/1,j}\),合法的\(j\)一定是一段区间,那么就完了。#include<iostream>#include<cstdio>#include<c......
  • M-SOLUTIONS Programming Contest
    A-SumofInteriorAngles答案为\(180(n-2)\)。#include<iostream>#include<cstdio>usingnamespacestd;intn;intmain(){ scanf("%d",&n); printf("%d",180*(n-2)); return0;}B-Sumo判断一下x的个数是否小于等于\(7\)。#......
  • Keyence Programming Contest 2020
    A-Painting每次取\(H,W\)中较大者涂就是了,输出\(\lceil\frac{n}{\max(H,W)}\rceil\)。代码:#include<iostream>#include<cstdio>usingnamespacestd;inth,w,n;intmain(){ scanf("%d%d%d",&h,&w,&n); if(h<w)swap(h,w); ......
  • NOMURA Programming Competition 2020
    A-StudyScheduling先算出总时间,然后在减去\(K\)就好了。代码:#include<iostream>#include<cstdio>usingnamespacestd;inth1,m1,h2,m2,k;intmain(){ scanf("%d%d%d%d%d",&h1,&m1,&h2,&m2,&k); intansh=h2-h1,ansm=m2-m1; if......
  • Social Infrastructure Information Systems Division, Hitachi Programming Contest
    A-HitachiString满足条件的串即为串长为偶数且相邻两个均为为hi,直接判断即可。代码:#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintN=15;intn;chars[N];intmain(){ scanf("%s",s+1); n=strlen(s+1); if(n&1) ......
  • Tokio Marine & Nichido Fire Insurance Programming Contest 2020
    A-Nickname直接输出前三个字符。代码:#include<iostream>#include<cstdio>usingnamespacestd;constintN=25;chars[N];intmain(){ scanf("%s",s+1); printf("%c%c%c",s[1],s[2],s[3]); return0;}B-Tag如果\(v\leqw\),则显然不......
  • DISCO Presents Discovery Channel Code Contest 2020 Qual
    A-DDCCFinals直接模拟即可。#include<iostream>#include<cstdio>usingnamespacestd;intx,y;intmain(){ scanf("%d%d",&x,&y); intans=0; if(x==1)ans+=30; elseif(x==2)ans+=20; elseif(x==3)ans+=10; if(y==1)ans+=30; ......