构造交互通信艾德毫克特殊题
LED灯道路
一个有向图,\(N \le 50000\),对边进行三色染色,要求不存在长度超过 \(42\) 的只有一种颜色的链。
这道构造题,考虑到 \(42^3 > n = 50000\),将整图三层分块,即每 \(42\) 条边分一小块,每 \(42\) 小块分一个大块,最后 \(\le 42\) 个大块为最终结果。
小块里面连 \(R\) 边,小块之间连 \(G\) 边,大块之间连 \(B\) 边。
不难发现,将不会出现长度超过 \(42\) 的同色链。
构造完成。
P12446 [COTS 2025] 答好位 / Vrsta
至多进行 \(K\) 次询问,每次可以询问一段区间 \([l, r]\),返回这段区间的次大值的下标。最后询问你 \([l, r]\) 区间内次大值的下标。
考虑打表判断。
对于序列 A = 5、2、9、6、8、3、4、1、7 ,我们把 \([l, r]\) 作为下标,打出这样一张表:

注意到,每个下标在表中最多出现在两个矩形内。
证明简单:对于下标 \(i\),记 \(pre_i\) 表示 \(i\) 前最后一个比 \(i\) 大的位置,\(nxt_i\) 表示 \(i\) 后第一个大于 \(i\) 的位置, \(pp_i\) 为 \(i\) 前倒数第二个大于 \(i\) 的,\(nn_i\) 为 \(i\) 后第二个大于 \(i\) 的。
则必定存在两个矩形满足条件,为:
故此得证。
所以我们得来做法:
我们取得一段区间 \([l, r]\) 的最大值 \(mx\) 和次大值 \(mxx\),则有矩形 \([l, mx] \times [mxx, r]\) 已知(假设 \(mx < mxx\))。
此时我们直接向 \([l, mxx - 1]\) 和 \([mx + 1, r]\) 递归即可。
加个记忆化就行。
总递归 \(2n\) 次,加上一开始需要找 \(mx\) 的 \(n\) 次,一共 \(3n\) 次询问,可做。
CODE
#include<bits/stdc++.h>
using namespace std;
int n;
int ans[3020][3020];
bool vis[3020][3020];
int qry(int x, int y){
cout<<"? "<<x<<' '<<y<<endl;
int res; cin>>res; return res;
}
void solve(int l, int r, int mx){
if(l == r) return ;
if(vis[l][r]) return ;
vis[l][r] = 1;
int mxx = qry(l, r), x, y;
tie(x, y) = minmax(mx, mxx);
for(int i = l; i <= x; i ++) for(int j = y; j <= r; j ++) ans[i][j] = mxx;
solve(l, y - 1, x), solve(x + 1, r, y);
}
signed main(){
int n; scanf("%d", &n);
int x = qry(1, n), l = x, r = x;
while(r < n && qry(l, r + 1) != x) r ++;
while(l > 1 && qry(l - 1, r) != x) l --;
int mx = (l == 1 ? r + 1 : l - 1);
solve(1, n, mx);
cout<<"!"<<endl;
int q; scanf("%d", &q);
while(q --){
int l, r; scanf("%d%d", &l, &r);
cout<<ans[l][r]<<endl;
}
return 0;
}
P3526 [POI 2011] OKR-Periodicity
定义 \(Pre(S)\) 为 \(S\) 的所有周期(即最后一个周期可以残缺)构成的集合,构造一个 \(01\) 字符串 \(T\),使得 \(Per(s) = Per(T)\)。
我们首先从特殊情况入手。
假如这个字符串没有周期,那么显然 \(00\cdots 01\) 就是一个合法的字符串。
接着我们考虑怎样求一个周期。
一个显然的结论是:一个字符串的周期,必然是它的最长 \(boarder\) 之长,这是一个经典的结论。

浙公网安备 33010602011771号