首先發現資料限制了只有k=1
k=1k=
1和k=
2k=2
k=2的情況,而且值域不是很大,或許可以暴力列舉平方根。
考慮k =1
k=1k=
1的情況,顯然直接列舉平方根,把不能同組出現的數標記一下就行了。
注意我們需要最小化分界的字典序,所以實際上是將字尾劃分得盡量長而已,倒著列舉即可。
考慮k =2
k=2k=
2的情況,仍然考慮列舉平方根,仍然考慮倒序列舉。
現在問題成了怎麼驗證。首先有乙個非常自然的思路,如果把所有有衝突的元素連邊之後是乙個二分圖的話,就合法。
顯然我們並不能直接跑二分圖。我們對於每個點u
uu建立反點v
vv。所有不能和u
uu同色的點必須和v
vv同色,並查集xjb維護一下就行了。
注意一種特殊情況。兩個數的和是乙個完全平方數,顯然我們只需要令它們不在同一集合即可,記錄一下出現次數就行了。
**實現注意細節
**:
#include
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace io
template
<
typename t>
inline t get()
inline
intgi()
}using
namespace io;
using std::cerr;
using std::cout;
cs int n=
3e5+
7,m=
512;
int n,k,mx,last;
int a[n]
,vis[n]
,tag[n]
,fa[n]
;int ans[n]
,cnt;
inline
intgf
(int u)
inline
void
solve1()
}if(flag)
vis[a[i]]=
true;}
}inline
void
solve2()
for(
int re j=
ceil
(sqrt
(a[i]))
;j<=m;
++j)}}
}else
int x1=
gf(a[i]
),x2=
gf(a[i]
+mx)
,y1=
gf(j*j-a[i]
),y2=
gf(j*j-a[i]
+mx);if
(x1==y1)
else}}
} finish:
if(flag)
last=i;
} vis[a[i]]++
;}}signed
main()
洛谷P3940 分組
好題 細節題 答案字典序要求最小,所以考慮倒敘列舉,對於當前一組需要盡量多的加東西,因為後面組選的數越多,前面的選擇機會越多 化列舉序列為列舉值域,這是這道題的關鍵 k 1 倒敘列舉到 i 此時只需判斷當前組中的數是否有加 a i 等於完全平方數的 可以 o n 列舉,但顯然可以更優 列舉所有的完全...
洛谷 P4447分組
大致想法是用乙個佇列記錄當前正在進行中分組的起始位置,並記錄當前分組數,若掃瞄到的下乙個數的個數少於當前分組數,則代表當前有一定數量的分組需要就此停止,按照開始順序依次出佇列即可 include include include include include include include incl...
洛谷p1525 並查集
先將最大的犯罪都找出來然後將人員分組 假設兩人x,y 如果x 前面已經有過敵人了 那就將y合併到x的敵人裡去 y也是如此若有 將x合併到y的敵人去 如果x 和 y前面都沒有 那麼互相將彼此設為敵人 直到找到矛盾的 就是 xy有同乙個敵人 include include include using n...