NOIP 模擬 9 分組
阿新 • • 發佈:2021-06-22
題解
這道題我們發現可以根據 \(k=1\) 和 \(k=2\) 的情況分別討論
\(k=1\) 時,我們發現要保證字典序,那麼我們從後往前掃,掃的時候判斷一下當前數是否會和上一段的衝突。
複雜度瓶頸就在於如何判斷。我們發現 \(a_i\leq 2^{17}\) 所以 \(j*j=a_i+a_k\) 中 \(j\) 最大為 \(2^9\),所以我們可以列舉 \(j\),記錄一個數組,判斷一下 \(j*j-a_i\) 是否出現過
最後若分出新的一段,記得要把前一段的清空。
\(k=2\) 時,我們可以把每個數拆成兩個點,分別為 \(x_1\),\(x_2\),\(y_1\),\(y_2\),讓後將衝突的數連起來,發現如果其符合二分圖,那麼就可以分為一組。
對於判斷二分圖,我們可以用並查集替代。(思想)
對於每個數,我們給他開一個敵人域,每次若發現衝突,但可以分成兩個團體解決,那麼我們將兩個樹的敵人域向與其發生衝突的數合併
判斷時就是判斷 \(x_1\) 是否和 \(y_1\) 在一個集合裡。
Code:
#include<bits/stdc++.h> #define ri register signed #define p(i) ++i using namespace std; namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++ inline int read() { ri x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();} return x*f; } } using IO::read; namespace nanfeng{ #define cmax(x,y) ((x)>(y)?(x):(y)) #define cmin(x,y) ((x)>(y)?(y):(x)) #define FI FILE *IN #define FO FILE *OUT static const int N=(1<<17)+7; int a[N],vis[N],st[N],fa[N<<1],fg[N<<1],n,k,tot=1,mx; int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);} inline int main() { // FI=freopen("nanfeng.in","r",stdin); // FO=freopen("nanfeng.out","w",stdout); n=read(),k=read(); for (ri i(1);i<=n;p(i)) a[i]=read(),mx=cmax(mx,a[i]); vis[a[n]]=1;st[1]=n; if (k==1) { for (ri i(n-1);i;--i) { for (ri j(ceil(sqrt(a[i])));j*j-a[i]<=mx;p(j)) { if (j*j>=a[i]&&vis[j*j-a[i]]) { st[p(tot)]=i; for (ri k(i+1);k<=st[tot-1];p(k)) vis[a[k]]=0; break; } } vis[a[i]]=1; } } else { for (ri i(1);i<=mx;p(i)) fa[i]=i,fa[i+mx]=i+mx; for (ri i(1);i*i<=(mx<<1);p(i)) fg[i*i]=1; for (ri i(n-1);i;--i) { ri fl=0; if (vis[a[i]]) { if (fg[a[i]<<1]) { if (vis[a[i]]==2||fa[a[i]+mx]!=a[i]+mx) fl=1; } } else { for (ri j(ceil(sqrt(a[i])));j*j-a[i]<=mx;p(j)) { if (vis[j*j-a[i]]) { if (fg[(j*j-a[i])<<1]&&vis[j*j-a[i]]==2) {fl=1;break;} int x1=find(a[i]),x2=find(a[i]+mx),y1=find(j*j-a[i]),y2=find(j*j-a[i]+mx); if (x1==y1) {fl=1;break;} fa[y2]=x1;fa[x2]=y1; } } } if (fl) { for (ri j(i);j<=st[tot];p(j)) fa[a[j]]=a[j],fa[a[j]+mx]=a[j]+mx,vis[a[j]]=0; st[p(tot)]=i; } p(vis[a[i]]); } } printf("%d\n",tot); for (ri i(tot);i>1;--i) printf("%d ",st[i]); puts(""); return 0; } } int main() {return nanfeng::main();}