CF1286C2
Posted chasedeath
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1286C2相关的知识,希望对你有一定的参考价值。
CF1286C2 - Madhouse (Hard version)
题目大意
交互器生成了一个串\\(s\\),可以用3次操作,每次
? l r
询问\\([l,r]\\)内所有连续子串,
交互器返回所有连续子串随机排列(字符位置和串的顺序均随机)的结果
额外要求:查询的总子串个数$\\leq \\lceil 0.777 (n+1)^2 \\rceil $
最后 ! s
输出答案
分析
看一看\\(0.777\\approx \\cfrac{7}{9}\\)
于是乎我就写了一个0.75的做法?
由于思路顺序极为奇怪,所以实现方法也很奇怪
从长到短确定
从\\(L=n,n-1,\\cdots 1\\)依次确定每一种长度的每一个串对应的字符集
假设当前知道\\(L+1\\)层的样子,可以通过相邻取交确定下一层除了第一个和最后一个的所有串
将他们删掉后,就知道当前头尾字符\\(s[n-L+1],s[L]\\)是什么
再确定头字符即可
确定头字符
考虑对于一个串,可以用以下方法两次求出整串
1.查询整串\\([1,n]\\)得到集合\\(S\\)
2.查询\\([2,n]\\)得到集合\\(T\\)
计算\\(S-T\\),即得到所有\\([1,i]\\)串的字符集,依次作差即可
用这个确定前半个串,消耗\\((\\frac{n}{2})^2\\)
结合前面的即可
代码实现比较奇怪
const int N=110,INF=1e9+10;
int n;
struct Node{
int c[26],n;
Node(){ memset(c,n=0,sizeof c); }
Node operator & (const Node __) const {
Node res;
rep(i,0,25) res.n+=res.c[i]=min(c[i],__.c[i]);
return res;
}
int operator < (const Node __) const {
if(n!=__.n) return n<__.n;
rep(i,0,25) if(c[i]!=__.c[i]) return c[i]<__.c[i];
return 0;
}
int operator == (const Node __) const {
rep(i,0,25) if(c[i]!=__.c[i]) return 0;
return 1;
}
char operator - (const Node __) const {
rep(i,0,25) if(c[i]>__.c[i]) return i+\'a\';
return -1;
}
void Show(){
cout<<"L="<<n<<\' \'; rep(i,0,25) rep(j,1,c[i]) putchar(i+\'a\');
puts("");
}
};
Node Read(){
static char s[N];
scanf("%s",s);
Node t;
for(int i=0;s[i];++i) t.n++,t.c[s[i]-\'a\']++;
return t;
}
char s[N];
void Sub1(){
int m=(n+1)/2;
multiset <Node> st;
printf("? %d %d\\n",1,m),fflush(stdout);
rep(i,1,m*(m+1)/2) st.insert(Read());
if(m>1) {
printf("? %d %d\\n",2,m),fflush(stdout);
rep(i,1,m*(m-1)/2) st.erase(st.find(Read()));
}
Node lst;
int p=0;
for(Node i:st) s[++p]=i-lst,lst=i;
}
multiset <Node> st[N];
Node A[N][N];
void Sub2(){
printf("? %d %d\\n",1,n),fflush(stdout);
rep(i,1,n*(n+1)/2) {
Node t=Read();
if(t.n==n) A[1][1]=t;
else st[t.n].insert(t);
}
//rep(i,1,n) {
//puts("---");
//for(auto j:st[i]) j.Show();
//}
rep(i,1,n/2) {
//cout<<"$"<<i<<\' \'<<s[i]<<endl;
//rep(j,1,i) A[i][j].Show();
rep(j,1,i-1) {
A[i][j].c[s[j]-\'a\']--,A[i][j].n--;
A[i+1][j+1]=A[i][j];
//cout<<"Erase: "; A[i+1][j+1].Show();
//for(auto t:st[n-i]) t.Show();
assert(st[n-i].find(A[i+1][j+1])!=st[n-i].end());
st[n-i].erase(st[n-i].find(A[i+1][j+1]));
A[i][j].c[s[j]-\'a\']++,A[i][j].n++;
}
Node a=*st[n-i].begin();
Node b=*st[n-i].rbegin();
Node x=A[i][1],y=A[i][i];
y.c[s[i]-\'a\']--;
s[n-i+1]=x-(a==y?b:a);
if(a==y) A[i+1][1]=b,A[i+1][i+1]=a;
else A[i+1][1]=a,A[i+1][i+1]=b;
//cout<<s[n-i+1]<<endl;
}
}
int main(){
n=rd();
Sub1(),Sub2();
printf("! ");
s[n+1]=0,puts(s+1);
fflush(stdout);
}
以上是关于CF1286C2的主要内容,如果未能解决你的问题,请参考以下文章
cf 1237 C2. Balanced Removals (Harder)
CF 949C Data Center Maintenance——思路+SCC
[CF]1526C2 Potions (Hard Version) 优先队列贪心