zoukankan      html  css  js  c++  java
  • 「题解」Codeforces 1394C Boboniu and String

    orz qyc

    两个串相似实际上是两个字符串 'N' 和 'B' 的数量一致。

    (s_i)(x_i) 个 'N',(y_i) 个 'B',(t)(x) 个 'N',(y) 个 'B'。

    分类讨论一下 (dist(s,t))(x,x_i) 以及 (y,y_i) 大小关系不同的四种情况下的取值。

    发现四种情况分别为:

    (x-y-x_i+y_i,-(x-y)+x_i-y_i,max(x_i-x,y_i-y),max(x-x_i,y-y_i))

    对出现的六个式子求 (max) 恰好为答案,具体为何同样可以分类讨论四种情况。

    二分答案转判定,就变成要求 (max) 里面六个值都 (geq mid)

    发现实际上是对 (x,y,x-y) 的取值范围作出限制。

    后面就很简单了,算出各自的取值范围,然后看前两项不等式的差出来的范围是否和后一项的范围有交即可,构造方案枚举个 (x) 随便怎么构造都可。

    其实分类讨论有很多细节,但是这里仅给出主要思路不商讨细节部分。

    //Code by do_while_true
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    typedef long long ll;
    template <typename T> T Max(T x, T y) { return x > y ? x : y; }
    template <typename T> T Min(T x, T y) { return x < y ? x : y; }
    template <typename T> T Abs(T x) { return x < 0 ? -x : x; }
    template <typename T> T chkmax(T &x, T y) { return x = x > y ? x : y; }
    template <typename T>
    T &read(T &r) {
    	r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    	while(ch >= '0' && ch <= '9') r = (r << 3) + (r <<1) + (ch ^ 48), ch = getchar();
    	return r = w ? -r : r;
    }
    const int N = 300010;
    const int INF = 100000000;
    int n, a[N], b[N];
    //a:N  b:B
    char ch[N];
    bool check(int x) {
    	int l1, r1, l2, r2, l3, r3;
    	l1 = -INF, r1 = INF; l2 = 0, r2 = INF; l3 = 0; r3 = INF;
    	for(int i = 1; i <= n; ++i) {
    		l1 = Max(l1, a[i]-b[i]-x);
    		r1 = Min(r1, a[i]-b[i]+x);
    		l2 = Max(l2, a[i]-x);
    		r2 = Min(r2, a[i]+x);
    		l3 = Max(l3, b[i]-x);
    		r3 = Min(r3, b[i]+x);
    	}
    	if(l2 < 0 || l3 < 0) return 0;
    	if(l1 > r1 || l2 > r2 || l3 > r3) return 0;
    	int l4 = l2 - r3, r4 = r2 - l3;
    	return r1 >= l4 && l1 <= r4;
    }
    signed main() { //freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
    	read(n);
    	if(n == 1) {
    		scanf("%s", ch+1);
    		puts("0");
    		printf("%s
    ", ch+1);
    		return 0;
    	}
    	for(int i = 1; i <= n; ++i) {
    		scanf("%s", ch+1);
    		int len = std::strlen(ch+1);
    		for(int j = 1; j <= len; ++j)
    			if(ch[j] == 'N') ++a[i];
    			else ++b[i];
    	}
    	int l = 0, r = INF, mid, ans = 0;
    	while(l <= r) {
    		mid = (l + r) >> 1;
    		if(check(mid)) ans = mid, r = mid-1;
    		else l = mid+1;
    	}
    	printf("%d
    ", ans);
    	int l1, r1, l2, r2, l3, r3;
    	l1 = -INF, r1 = INF; l2 = 0, r2 = INF; l3 = 0; r3 = INF;
    	for(int i = 1; i <= n; ++i) {
    		l1 = Max(l1, a[i]-b[i]-ans);
    		r1 = Min(r1, a[i]-b[i]+ans);
    		l2 = Max(l2, a[i]-ans);
    		r2 = Min(r2, a[i]+ans);
    		l3 = Max(l3, b[i]-ans);
    		r3 = Min(r3, b[i]+ans);
    	}
    	int l4 = l2 - r3, r4 = r2 - l3;
    	l = Max(l1, l4); r = Min(r1, r4);
    	for(int i = l2; i <= r2; ++i) {
    		int _l = i - r3, _r = i - l3;
    		if(Max(_l, l) <= Min(r, _r)) {
    			int p = Max(_l, l);
    			if(i || (i-p)) {
    				for(int j = 1; j <= i-p; ++j) printf("B");
    				for(int j = 1; j <= i; ++j) printf("N");
    				return 0;
    			}
    			else {
    				p = Min(r, _r);
    				if(i || (i-p)) {
    					for(int j = 1; j <= i-p; ++j) printf("B");
    					for(int j = 1; j <= i; ++j) printf("N");
    					return 0;
    				}
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    基于2.0 创建旧模板项目
    vue 脚手架 图形化界面操作
    webpack 相关配置 (1)
    ES6模块化 babel
    处理时间函数
    问题集-- SQL 约束名不能重复
    SQL 必知必会-- 第17课:创建和操作表
    SQL 必知必会-- 第1课:数据库基础和什么是SQL
    Java SE ---类,方法,对象等
    Java SE ---控制流程:break与continue语句
  • 原文地址:https://www.cnblogs.com/do-while-true/p/15047880.html
Copyright © 2011-2022 走看看