codeforces 875C - National Property
http://codeforces.com/contest/875/problem/C
题意:给你 n 个字符串,每个字符串的字符为 1 到 m,可以使所有字符串中某个相同字符变成大写字符,如 1 -> 1'。定义所有大写字符均小于小写字符, 如:2 < 3, 2' < 3', 3' < 2,让你求是否可以转变某些字符,是 n 个字符串字典序升序排序。
题解:大暴力过去。dfs(int l, int r, int id) 表示字符串 [ l , r ] 的前 id 个字符完全相同,现在从第 id+1个字符开始算,也就是只有看第 di+1列字符是否升序排序就好,由于第 id+1 列的字符变成大写 会影响到 id 前的列数,所以这次做完再次dfs就行。
#include<cstdio> #include<string> #include<cmath> #include<algorithm> #include<iostream> #include<cstring> #include<set> #define oo 0x3f3f3f3f #define mod 1000000007 using namespace std; const int MAXN = 100000+10; const int MAXM = 100000+10; int a[MAXM]; bool cg[MAXN]; vector<int> ve[MAXN]; int fact(int id) { if(cg[id]) return a[id]-100000; return a[id]; } bool ans, ok; void dfs(int l, int r, int id) { if( !ans ) return ; if(l >= r) return ; while(l <= r && id >= ve[l].size() ) l++; for(int i = l+1; i <= r; ++i) { if(id >= ve[i].size()) { ans = false; return ; } if( fact(ve[i][id]) < fact(ve[i-1][id]) ) { for(int j = i-1; j >= l; --j) { if( fact(ve[j+1][id]) > fact(ve[j][id]) ) { break; } if( !cg[ ve[j][id] ] ) { ok = true; } cg[ ve[j][id] ] = true; if( fact(ve[j+1][id]) < fact(ve[j][id]) ) { ans = false; return ; } } } } int kk = l; for(int i = l; i <= r; ++i) { if(ve[i][id]!=ve[kk][id]) { dfs(kk, i-1, id+1); if(!ans) return ; kk = i; } if(i==r&&ve[i][id]==ve[kk][id]) { dfs(kk, i, id+1); if(!ans) return ; } } } int main (void) { ios::sync_with_stdio(false); int n, m; cin >> n >> m; memset(cg, false, sizeof(cg)); for(int i = 1; i <= m; ++i) { a[i] = i; } for(int i = 1; i <= n; ++i) { int l; cin >> l; for(int j = 1; j <= l; j++) { int x; cin >> x; ve[i].push_back(x); } } ans = true; ok = true; while(ok && ans) { ok = false; dfs(1, n, 0); } dfs(1, n, 0); if(!ans) { cout << "No"; return 0; } int sum = 0; for(int i = 1; i <= m; ++i) { if(cg[i]) ++sum; } cout << "Yes" << endl; cout << sum << endl; for(int i = 1; i <= m; ++i) { if(cg[i]) cout<<i<<' '; } }