• CF875C National Property


    题目描述

    给定一些字符串,其中字母用数字表示,并且初始是小写的。你可以把一些小写字母改成大写,但同时你要把所有同种字母全部改成大写。问是否能经过一些操作使得最终的字符串序列满足按字典序升序排列。如果能,则需要输出方案。

    题解

    可以把每个字母看成点,有大写和小写俩种情况。若对于俩个相邻的字符串来说,字典序大小的比较其实是第一个不相同的字符,找到那个不相同的位置,可能不存在,假设存在设为x,若i的字典序大于i - 1的,则这俩行的x位置的大小写情况应该相同。若i-1的字典序大于i的,则说明必然是i-1在x的字符是大写,在i的x字符必然是小写,这题其实看似像扩展域并查集,但在并查集上无法体现&关系,只能2-SAT。

     1 #include <bits/stdc++.h>
     2 #define MAX 200005
     3 using namespace std;
     4  
     5 int n, m, cnt, tot;
     6 int len, lst[MAX], a[MAX], col[MAX];
     7 int head[MAX], Next[MAX*2], vet[MAX*2];
     8  
     9 void add(int x, int y){
    10     cnt++;
    11     Next[cnt] = head[x];
    12     head[x] = cnt;
    13     vet[cnt] = y;
    14 }
    15  
    16 int low[MAX], dfn[MAX], vis[MAX], T;
    17 stack<int> s;
    18 void tarjan(int x){
    19     low[x] = dfn[x] = ++T;
    20     vis[x] = true;
    21     s.push(x);
    22     for(int i = head[x]; i; i = Next[i]){
    23         int v = vet[i];
    24         if(!dfn[v]){
    25             tarjan(v);
    26             low[x] = min(low[x], low[v]);
    27         }
    28         else if(vis[v]){
    29             low[x] = min(low[x], dfn[v]);
    30         }
    31     }
    32     if(low[x] == dfn[x]){
    33         tot++;
    34         int t = -1;
    35         while(t != x){
    36             t = s.top();
    37             s.pop();
    38             vis[t] = false;
    39             col[t] = tot;
    40         }
    41     }
    42 }
    43  
    44 int main()
    45 {
    46     cin >> m >> n;
    47     for(int i = 1; i <= m; i++){
    48         int t;
    49         scanf("%d", &t);
    50         for(int j = 1; j <= t; j++){
    51             scanf("%d", &a[j]);
    52         }
    53         for(int j = 1; j <= min(len, t); j++){
    54             if(lst[j] < a[j]){
    55                 add(a[j] + n, lst[j] + n);
    56                 add(lst[j], a[j]);
    57                 break;
    58             }
    59             else if(lst[j] > a[j]){
    60                 add(lst[j], lst[j] + n);
    61                 add(a[j] + n, a[j]);
    62                 break;
    63             }
    64             if(j == min(len, t) && len > t){
    65                 puts("No");
    66                 return 0;
    67             }
    68         }
    69         len = t;
    70         for(int j = 1; j <= t; j++) lst[j] = a[j];
    71     }
    72     
    73     for(int i = 1; i <= n*2; i++){
    74         if(!dfn[i]) tarjan(i);
    75     }
    76     for(int i = 1; i <= n; i++){
    77         if(col[i] == col[i+n]){
    78             puts("No");
    79             return 0;
    80         }
    81     }
    82     
    83     puts("Yes");
    84     int ans = 0;
    85     for(int i = 1; i <= n; i++){
    86         if(col[i] > col[i+n]){
    87             ans++;
    88         }
    89     }
    90     cout << ans << endl;
    91     for(int i = 1; i <= n; i++){
    92         if(col[i] > col[i+n]){
    93             printf("%d ", i);
    94         }
    95     }
    96     
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    一条代码快速解决滚动条隐藏问题
    微信小程序:wx:for循环输出的使用方法以及简单例子
    点运算符(.)和中括号运算符([])有哪些区别
    线程
    ArrayMap 和HashMap的区别
    Android加载图片的策略
    Android图片加载为什么选择glide
    Android 设计模式对比
    Android 注解框架对比
    ReactNative编写规范
  • 原文地址:https://www.cnblogs.com/xwdzuishuai/p/14032129.html
Copyright © 2020-2023  润新知