【题解】NOIP2022 喵了个喵
个人感觉难度不如移球游戏。
首先对于 的情况,我们用前面 栈,保持每个栈大小不超过 ,这样每加入一张新牌,如果在前 个栈里出现了,就可以通过第 个栈消掉, 号栈记为特殊栈。
对于 的情况。这是会多出来一种情况,就是前面 个栈填满了 个不同的牌。现在又来了一张新牌,如果直接放第 个栈会影响后面的消去。
不妨记 为这张新牌。那么我们讨论将这个 放到哪。那么现在我们只关心 到下一个 之间的牌,显然这些牌不包含 ,且全部在前 个栈内出现恰好一次。
如果这些牌全部在栈顶,则将 放到特殊栈(在代码中为 type 1)。
否则我们记第一个出现在栈底的牌记为 。 所在栈上面的牌为 。
如果 出现了偶数次,那么就把 放在 上面, 放到特殊栈,最后通过 操作把 消掉(代码中为 type 3)。
否则我们把 放到特殊栈,最后一定能把 都消掉,然后把 所在的栈记为新的特殊栈(代码中为 type 2)。
这样我们通过简单讨论解决了这道题。我认为这题唯一的难点在于想到特殊栈会移动。其余的对于省一选手应该都是基操。
#define N 605
#define M 2000005
int n, m, kk, res, id;
int a[M], c[N], u[N], up[N], dn[N], p[N];
struct node{int op, x, y;};
queue<int>q; vector<node>ans;
void clear(){
memset(c, 0, sizeof(c));
memset(u, 0, sizeof(u));
memset(up, 0, sizeof(up));
memset(dn, 0, sizeof(dn));
memset(p, 0, sizeof(p));
while(!q.empty())q.pop();
id = n, res = 2 * (n - 1);
rp(i, n - 1)q.push(i), q.push(i);
ans.clear();
}
void ed(int x){ans.pb(node{1, x, 0});}
void ed(int x,int y){ans.pb(node{2, x, y}); }
void match(int w){
//assert(c[w]);
int ps = c[w];
if(u[w] == 1){
ed(id), ed(ps, id);
if(p[ps] == 2)u[up[ps]]--, dn[ps] = up[ps];
p[ps] --, c[w] = 0, q.push(ps);
}
else{
ed(ps), c[w] = 0, p[ps] --, q.push(ps);
}
res ++;
}
void ins(int x){
while(!q.empty() && (p[q.front()] == 2 || q.front() == id))q.pop();
int y = q.front(); q.pop();
if(p[y] == 0)dn[y] = x, c[x] = y, u[x] = 1;
else up[y] = x, c[x] = y, u[x] = 2;
ed(y), p[y] ++, res --;
}
int calc(int s){
int t = s + 1;
while(a[t] != a[s] && u[a[t]] == 2)t++;
if(a[t] == a[s]){ //type 1
ed(id);
rep(i, s + 1, t - 1)
if(c[a[i]])match(a[i]); else ins(a[i]);
ed(id);
}
else{
int y = c[a[t]], k = up[y], op = 0;
rep(i, s + 1, t - 1)if(a[i] == k)op ^= 1;
if(op){ //type 2
ed(id);
rep(i, s + 1, t - 1){
if(a[i] == k)ed(y);
else if(c[a[i]])match(a[i]);
else ins(a[i]);
}
ed(y);
c[k] = 0, c[a[t]] = 0,
c[a[s]] = id, dn[id] = a[s], u[a[s]] = 1, p[id] = 1;
res += 1, q.push(id), id = y, p[y] = 0;
}
else{ //type 3
ed(y);
rep(i, s + 1, t - 1){
if(a[i] == k)ed(id);
else if(c[a[i]])match(a[i]);
else ins(a[i]);
}
ed(id), ed(id, y);
c[a[t]] = 0, u[k] = 1, dn[y] = k, up[y] = a[s];
c[a[s]] = y, u[a[s]] = 2;
}
}return t;
}
void solve(){
read(n, m, kk), clear();
rp(i, m)read(a[i]);
for(int i = 1; i <= m; i ++){
if(c[a[i]])match(a[i]);
else{
if(res)ins(a[i]);
else i = calc(i);
}
}
printf("%d\n", si(ans));
go(x, ans){
if(1 == x.op)printf("1 %d\n", x.x);
else printf("2 %d %d\n", x.x, x.y);
}
}
int main() {int T; read(T); while(T--)solve();}
作者:7KByte
出处:https://www.cnblogs.com/7KByte/p/16930110.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2021-11-27 【游记】NOIP2021