zoukankan      html  css  js  c++  java
  • codeforces1304D Shortest and Longest LIS Dilworth定理

    网址:https://codeforces.com/contest/1304/problem/D

    题意:

    给出一些长度是$n-1$的偏序关系,然后往这些偏序关系中填入$1$到$n$这$n$个数。求合法的序列中最短和最长的上升子序列的方案。

    题解:

    $Dilworth$定理:最长不下降子序列长度$=$最少下降子序列的划分$=$最小反链划分。

    $Dilworth$定理的对偶定理:最长不上升子序列长度$=$最少上升子序列的划分$=$最大反链划分。

    $*Dilworth$定理中反链的解释:设全集$U$是一个偏序集,$U$的子集中,满足其中任意两个元素(不相同)不可比的集合。

    根据这个定理首先是求最小的:我们先把所有的$n$个数反着放,然后显然这个是最短的上升子序列。然后对于$'<'$,我们就整段反过来,然后一直这样子处理到结尾。为什么这样做是对的呢?因为这样子一定是最少的上升子序列的划分,对于最大的,同理操作即可。

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 5;
    int mx[N], mi[N];
    char s[N];
    void solve()
    {
    	int n;
    	scanf("%d%s", &n, s + 1);
    	for (int i = 1; i <= n; ++i)
    		mx[i] = i, mi[i] = n - i + 1;
    	for (int i = 1; i < n;)
    	{
    		char ch = s[i];
    		int k = i + 1;
    		while (k < n && s[k] == s[i])
    			++k;
    		if (ch == '<')
    			reverse(mi + i, mi + k + 1);
    		else
    			reverse(mx + i, mx + k + 1);
    		i = k;
    	}
    	for (int i = 1; i <= n; ++i)
    		printf("%d%c", mi[i], " 
    "[i == n]);
    	for (int i = 1; i <= n; ++i)
    		printf("%d%c", mx[i], " 
    "[i == n]);
    }
    int main()
    {
    	int t;
    	scanf("%d", &t);
    	while (t--)
    		solve();
    	return 0;
    }
    

    $*$为什么能得到上面那个连等关系:

    把序列转化成集合,我们发现对于一个序列的元素,有两个量描述:使用有序数对$(p,v)$表示原序列中的一个数。$p$表示位置,$v$表示数值。对于求最长不下降子序列的,应该满足的关系是$p1<=v1$且$p2<=v2$,这是个偏序关系显然可比。所以满足$Dilworth$定理。对于其他偏序关系同理。

  • 相关阅读:
    (转)Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id)等
    (转)Objective-C语言--属性和实例变量
    (转)iOS 属性字符串
    (转)git clone: error: RPC failed; result=18, HTTP code = 200 解决办法
    iOS设置UINavigationBar 的样式
    Install kubernetes without yum
    kubernetes install for centos
    Deploying docker registry v2
    build docker deivcemapper
    docker local registry server gave HTTP response to HTTPS client
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/12319146.html
Copyright © 2011-2022 走看看