• [atAGC054D]ox


    对于两个字符串$s$和$t$(保证其中每一种字符个数相同),定义$s$和$t$的相对逆序对数为$s$得到$t$的最少交换次数,显然同种字符相对顺序保持不变,因此即依次编号后的逆序对数

    问题不妨看作构造合法字符串$t$使得$s$和$t$的相对逆序对数最小,定义$f_{S}(s)$为$s$仅保留$S$中的字符后所得到的字符串,那么有以下两个结论——

    结论1:当$S={(,)}$时,若$t$是使得$s$和$t$相对逆序对数最小的合法字符串,则$f_{S}(t)$也是使得$f_{S}(s)$和$f_{S}(t)$相对逆序对数最小的合法字符串

    结论2:当$S={o,x}$时,若$t$是使得$s$和$t$相对逆序对数最小的合法字符串,则$f_{S}(s)=f_{S}(t)$

    由此,不妨先求出$S={(,)}$时的$f_{S}(t)$,进而即将$o$和$x$从左到右依次插入,显然这可以用一个二维dp计算,条件为$x$之前左括号数严格大于右括号数,计算答案考虑逆序对数即可

    时间复杂度为$o(n^{2})$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 8005
     4 queue<int>q;
     5 vector<int>vb,vc;
     6 int n,cnt,ans,sum[N],f[N][N];
     7 char s[N]; 
     8 int main(){
     9     scanf("%s",s+1);
    10     n=strlen(s+1);
    11     vb.push_back(0),vc.push_back(0);
    12     for(int i=1;i<=n;i++){
    13         if (s[i]=='('){
    14             cnt++;
    15             vb.push_back(i);
    16             if (!q.empty()){
    17                 vb.push_back(q.front());
    18                 q.pop();
    19             }
    20         }
    21         if (s[i]==')'){
    22             cnt--;
    23             if (cnt<0)q.push(i);
    24             else vb.push_back(i);
    25         }
    26         if ((s[i]=='o')||(s[i]=='x'))vc.push_back(i);
    27     }
    28     for(int i=1;i<vb.size();i++){
    29         sum[i]=sum[i-1];
    30         if (s[vb[i]]=='(')sum[i]++;
    31         else sum[i]--;
    32     }
    33     memset(f,0x3f,sizeof(f));
    34     memset(f[0],0,sizeof(f[0]));
    35     for(int i=1;i<vc.size();i++){
    36         cnt=0;
    37         for(int j=0;j<vb.size();j++)
    38             if (vc[i]>vb[j])cnt++;
    39         for(int j=0;j<vb.size();j++){
    40             if (vc[i]<vb[j])cnt++;
    41             else cnt--;
    42             if ((s[vc[i]]=='o')||(sum[j]))f[i][j]=min(f[i][j],f[i-1][j]+cnt);
    43         }
    44         for(int j=1;j<vb.size();j++)f[i][j]=min(f[i][j],f[i][j-1]);
    45     }
    46     ans=0x3f3f3f3f;
    47     for(int i=0;i<vb.size();i++)ans=min(ans,f[(int)vc.size()-1][i]);
    48     for(int i=1;i<vb.size();i++)
    49         for(int j=i+1;j<vb.size();j++)
    50             if (vb[i]>vb[j])ans++;
    51     printf("%d
    ",ans);
    52     return 0;
    53 } 
    View Code
  • 相关阅读:
    随手记十——淘宝静态页面
    随手记九——溢出文字处理、背景图片填充、图片代替文字
    随手记八——关于伪元素和仿淘宝导航栏
    随手记七——关于float的一个上节没明白的问题
    随手记六——两个经典BUG和bfc
    随手记五——盒子模型和层模型
    随手记四——一些课堂笔记和小技巧、总结
    随手记三——理解相邻兄弟选择器的辛酸过程
    随手记二——CSS样式和选择器
    jQuery实现手风琴效果
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15361883.html
Copyright © 2020-2023  润新知