21.6.24 t1
阿新 • • 發佈:2021-06-24
tag:構造
答案為no只有兩種情況:
- 有一個顏色沒有出現過
- 兩個相鄰的點同色
其他情況一定是yes。
具體構造方案為:每次找到一組連續 \(3\) 不同色的點,且中間那個點的顏色出現多於1次,然後將這個三角形切掉,繼續遞迴處理。
這樣一次操作之後顯然是不會違反上述性質的。
程式碼實現可以使用一個數組維護可能作為中間點的那些點。
一次刪除操作最多隻會影響到2個點,所以空間開3倍就夠了。
#include<bits/stdc++.h> using namespace std; template<typename T> inline void Read(T &n){ char ch; bool flag=false; while(!isdigit(ch=getchar()))if(ch=='-')flag=true; for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48)); if(flag)n=-n; } enum{ MAXN = 100005 }; int n, a[MAXN], l[MAXN], r[MAXN]; int q[3*MAXN], top, cnt[3]; char vis[MAXN]; inline void check(int x){if(a[l[x]]!=a[x] and a[x]!=a[r[x]] and a[r[x]]!=a[l[x]]) vis[x] = true, q[++top] = x;} inline void del(int x){ printf("%d %d\n",l[x],r[x]); r[l[x]] = r[x]; l[r[x]] = l[x]; vis[l[x]] = vis[r[x]] = vis[x] = false; cnt[a[x]]--; check(l[x]); check(r[x]); } int main(){ Read(n); for(int i=1; i<=n; i++) Read(a[i]); for(int i=2; i<=n; i++) l[i] = i-1; l[1] = n; for(int i=1; i<n; i++) r[i] = i+1; r[n] = 1; for(int i=1; i<=n; i++) check(i), cnt[a[i]]++; for(int i=0; i<3; i++) if(cnt[i]==0) return puts("no"), 0; for(int i=1; i<n; i++) if(a[i]==a[i+1]) return puts("no"), 0; if(a[1]==a[n]) return puts("no"), 0; puts("yes"); for(int i=1, rem=n; i<=top and rem>3; i++) if(cnt[a[q[i]]]>1 and vis[q[i]]) del(q[i]), rem--; return 0; }