• CF1286C2


    CF1286C2 - Madhouse (Hard version)

    题目大意

    交互器生成了一个串(s),可以用3次操作,每次

    ? l r 询问([l,r])内所有连续子串,

    交互器返回所有连续子串随机排列(字符位置和串的顺序均随机)的结果

    额外要求:查询的总子串个数$leq lceil 0.777 (n+1)^2 ceil $

    最后 ! s 输出答案


    分析

    看一看(0.777approx 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
    ",1,m),fflush(stdout);
    	rep(i,1,m*(m+1)/2) st.insert(Read());
    	if(m>1) {
    		printf("? %d %d
    ",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
    ",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);
    }
    
    
    
    
    
    
  • 相关阅读:
    数据库之ORACLE常见基础操作
    数据库基础之Oracle函数
    Snuketoon [ABC217H]
    Cards [CF1278F]
    Squirrel Migration [ARC087F]
    Xor Query [ABC223H]
    Three Permutations [ABC214G]
    雨林跳跃[APIO2021]
    Redis5.0 主从模式和高可用 搭建和测试报告
    Redis5 压力测试结果反馈报告
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14825130.html
Copyright © 2020-2023  润新知