CF875C National Property (題解)
阿新 • • 發佈:2021-07-14
P.S.
妙妙題
Description.
給定一些字串,你需要給他們確定大小寫,使得字串字典序遞增。
Solution.
首先很顯然,遞增只需要 \(n-1\) 對相鄰字串都滿足 \(S_{i-1}<S_{i}\)。
那麼我們比較相鄰字串,發現必定有一段兩個字串相同。
我們分類討論下一位:
- 下一位在第一個字串中不存在——必定成立
- 下一位在第二個字串中不存在——必定無解
- 下一位在兩個字串中都存在——比較複雜,是後文重點解決的問題。
那麼我們現在需要考慮如何計算第三類的答案。
剛開始覺得好像只需要一個拓撲排序就好了,然後怒斥是大水題,然後發現自己假地很慘。
沒想到 2-sat 問題,應該是沒想的很深
如果想到了 2-sat,那這題就做完了。
就考慮分類討論:
- \(a<b\),那 \(a\) 取小寫能推出 \(b\) 取小寫,\(b\) 取大寫能推出 \(a\) 取大寫。
- \(a>b\),那隻可能是 \(a\) 取大寫,\(b\) 取小寫。
然後套上 2-sat 模板即可。
Coding.
點選檢視垃圾程式碼
//是啊,你就是那隻鬼了,所以被你碰到以後,就輪到我變成鬼了{{{ #include<bits/stdc++.h> using namespace std;typedef long long ll; template<typename T>inline void read(T &x) { x=0;char c=getchar(),f=0; for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1; for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48); f?x=-x:x; }/*}}}*/ struct edge{int to,nxt;}e[400005];int n,m,et,head[200005]; int buf[200005],*a[100005],ln[100005],tt,st[200005],tp; int dfn[200005],dt,low[200005],cl[200005],ct;char v[200005]; inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;} inline void add(int x,int y) {//x表示大寫,x+m表示小寫,x<y if(x<y) adde(x+m,y+m),adde(y,x); if(x>y) adde(x+m,x),adde(y,y+m); } inline void tarjan(int x) { dfn[x]=low[x]=++dt,v[x]=1,st[++tp]=x; for(int i=head[x];i;i=e[i].nxt) if(!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[e[i].to],low[x]); else if(v[e[i].to]) low[x]=min(dfn[e[i].to],low[x]); if(dfn[x]==low[x]) {int y=++ct;do v[y=st[tp--]]=0,cl[y]=ct;while(y^x);} } int main() { read(n),read(m),a[1]=buf;for(int i=1;i<=n;i++) { read(ln[i]),a[i+1]=a[i]+ln[i]; for(int j=1;j<=ln[i];j++) read(a[i][j]); } for(int i=2;i<=n;i++) { char fg=1;for(int j=1;j<=ln[i]&&j<=ln[i-1]&&fg;j++) if(a[i][j]^a[i-1][j]) add(a[i-1][j],a[i][j]),fg=0; if(fg&&ln[i]<ln[i-1]) return puts("No"),0; } for(int i=1;i<=m+m;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=m;i++) if(cl[i]==cl[i+m]) return puts("No"),0; int cnt=0;puts("Yes");for(int i=1;i<=m;i++) if(cl[i]<cl[i+m]) cnt++; printf("%d\n",cnt);for(int i=1;i<=m;i++) if(cl[i]<cl[i+m]) printf("%d ",i); return putchar('\n'),0; }