1 条题解
-
0
记有毒细菌为 ,无毒细菌为 .
考虑每次询问时如何通过每个时刻的细菌数量得到每个 连续段的长度.
设 为时刻 剩余的 的数量, 为初始 的数量.
当询问串是全 或全 时,都会返回没有细菌死亡.
其余情况,对于一个长为 的 连续段,若其在开头或末尾,则其会让 加 ,否则会让 加 .
先假设所有 连续段都在中间. 我们求出 的二阶差分 . 那么对于一个长为 的 连续段,若 为奇数,则其会使 $a_{\lfloor\frac s2\rfloor},a_{\lceil\frac s2\rceil}$ 加 ,否则会使 加 .
如果把两个长为 的连续段分别替换为长为 的连续段,那么返回的结果不变. 但是 若保证所有长为奇数的连续段长度互不相同,则可以唯一还原出每个连续段长度.
假设我们已经找到了某个 的位置 . 考虑求出 的值,那么我们可以这样构造:
1 w 2 2 w 3 3 3 w .... 若存在一个长为 的连续段,则意味着 ,否则 . 这样一次可以查询 个数的值.考虑如何找到第一个 的位置. 我们这样询问:
1 1 ... 1 1 2 3 ... 100,其中1的个数为 . 若没有细菌死亡,则意味着 相同,可以把 扔掉变成一个大小为 的问题. 否则,若最后剩余细菌 ,则 ,若剩余细菌 ,则可以通过细菌存活时间推断出第一个连续段长度,从而得到第一个细菌.现在问题变为在 次询问内查询 个数的值,也就是说每次查询我们需要得到 个数.
之前的构造中所有连续段长度互不相等,现在我们希望长为偶数的连续段出现多次. 例如,我们构造
1 1和2 2 w 2 2和3 3 w 3 3 w 3 3 w 3 3,根据长为 的连续段数量在二进制下每一位的值,我们可以得到 的值.写个程序计算可以发现可以得到 个数的值. 现在还差一个数. 注意到之前我们都假设询问串开头和结尾都是
1,考虑在两端动手脚. 由于两端 连续段存活的时间是中间的两倍,因此我们可以把 连续段从中间挪到两端,然后让长度除以 . 这样就能多询问一个数了.#include<bits/stdc++.h> #include "toxic.h" #define fo(i,l,r) for(int i=(l);i<=(r);++i) #define fd(i,l,r) for(int i=(l);i>=(r);--i) #define fu(i,l,r) for(int i=(l);i<(r);++i) #define pi pair<int,int> #define eb emplace_back #define vi vector<int> #define fi first #define se second #define ll long long using namespace std; const int N=1007; int o,m,b[N],s[N],h[N]; pi a[N]; void determine_type(int n) { fo(i,1,3) { int l=(i-1)*333+1,r=i*333+1; vi v; fo(j,1,333) v.eb(l-1); fo(j,l,r) v.eb(j-1); vi t=query_machine(v); int w=t.back(); if(w==v.size()) continue; if(w<333) o=l+t.size()-333; else { o=l; fo(j,1,o) s[j]=1; } break; } a[m=1]={19,1}; fo(i,1,50) { if(i&1){a[++m]={i,1};continue;} fo(j,0,3) a[++m]={((i+1)<<j)-1,1<<j}; } sort(a+2,a+m+1); a[m=50]={20,1}; for(int r=n;r>=o;r-=50) { int l=r-49; vi v; fo(i,1,50) { fo(j,1,a[i].se) { fo(k,1,a[i].fi/a[i].se) v.eb(l+i-2); v.eb(o-1); } } v.pop_back(); vi w=query_machine(v); b[1]=v.size()-w.back(); fu(i,0,w.size()) b[2+i]=w[i]-w.back(); fo(i,1,48) b[i]=b[i]-2*b[i+1]+b[i+2]; if(b[19]&1) b[19]--; else s[l]=1; if(b[20]&1) b[20]--; else s[r]=1; fd(i,18,1) { while(b[i]>1) b[i]-=2,h[i+i]++; if(b[i]) b[i]--,b[i-1]--,h[i+i-1]++; } fo(i,2,49) s[l+i-1]=!(h[a[i].fi/a[i].se]&a[i].se); fo(i,0,50) b[i]=h[i]=0; } vector<char>v; fo(i,1,n) v.eb(s[i]?'T':'R'); answer_type(v); }
- 1
信息
- ID
- 11009
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者