• CR655 题解


    A. Omkar and Completion

    直接输出 \(n\) 个一样的数即可。

    B. Omkar and Last Class of Math

    找最大的因数即可。我们也可以转化为找最小的因数。注意若原数为质数则令 \(a=1\)

    C. Omkar and Baseball

    诈骗题。若全部就位则输出 \(0\),若错位的连续则输出 \(1\),否则一次将其全部错位再用一次恢复。

    D. Omkar and Circle

    我们考虑最终删去了哪些数。如果存在两数连续,那么它们就一定还带了一个数,严格劣于选择两边的数。

    故问题转化为找 \([\frac{n}{2}]\) 个不相邻的数最小。

    E. Omkar and Last Floor

    区间 \(\text{dp}\) 的难点在于想到它。

    考虑区间 \(\text{dp}\),考虑一种策略,由于函数是凸的,我们一定希望区间中的一列尽可能地大。

    于是有转移 \(dp_{l,r}=\max\limits_{k\in [l,r]} dp_{l,k-1}+dp_{k+1,r}+(\text{区间内且包含 k})^2\)

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 1e9
    const int maxn=2e5+10;
    const int mod=1e9+7;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    const int N=105;
    int n,m,dp[N][N],lft[N][N],rht[N][N];
    int main(){
    	n=read(),m=read();
    	for(int i=1;i<=n;i++){
    		int k=read();
    		for(int j=1;j<=k;j++){
    			int l=read(),r=read();
    			for(int p=l;p<=r;p++)
    				lft[i][p]=l,rht[i][p]=r;
    		}
    	}
    	for(int len=1;len<=m;len++)
    		for(int l=1;l+len-1<=m;l++){
    			int r=l+len-1;
    			for(int k=l;k<=r;k++){
    				int cnt=0;
    				for(int i=1;i<=n;i++)
    					if(lft[i][k]>=l&&rht[i][k]<=r)cnt++;
    				dp[l][r]=max(dp[l][r],cnt*cnt+dp[l][k-1]+dp[k+1][r]);
    			}
    		}
    	printf("%d\n",dp[1][m]);
    	return 0;
    }
    
    

    F. Omkar and Modes

    吐槽一句,这个不降的条件在翻译里属实是有些隐蔽。

    考虑分治地处理,用 \(solve(l,r)\) 求出区间 \([l,r]\) 内的所有数值。

    求一遍区间众数 \(x\) 和出现次数 \(y\)。若我们已经知道一个位置 \(a_p=x\) ,则我们可以使用两次询问求出这个区间。

    具体地,我们知道 \([p-y+1,p]\)\([p,p+y-1]\) 之间一定至少有一个的众数也为 \(x\)

    如果我们还不知道,那么隔 \(y\) 询问一个单点,注意到我们询问的每一个数都不同,且一定可以询问到一个 \(x\)

    但是这样还是会有很多重复的询问浪费了,于是我们利用以前的信息,从之前的最后一个比 \(x\) 小的数的位置开始。

    这样的话,询问区间众数一个 \(k\),询问每个单点一个 \(k\),确定区间两个 \(k\),正好 \(4k\),做完了。

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 1e9
    const int maxn=2e5+10;
    const int mod=1e9+7;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    int n,m,a[maxn];
    #define pii pair<int,int>
    #define mkp make_pair
    #define fi first
    #define se second
    map<int,int>mp;
    map<int,int>::iterator it;
    inline pii ask(int l,int r){
    	if(l<1)l=1;if(r>n)r=n;
    	if(l>r)return mkp(0,0);
    	printf("? %d %d\n",l,r);
    	fflush(stdout);
    	int x=read(),y=read();
    	return mkp(x,y);
    }
    inline void solve(int l,int r){
    	if(l>r)return;
    	//printf("solving interval:[%d,%d]\n",l,r);
    	pii now=ask(l,r);
    	int x=now.fi,y=now.se;
    	if(r-l+1==y){
    		for(int i=l;i<=r;i++)a[i]=x;
    		mp[x]=l;return;
    	}
    	if(!mp[x]){
    		it=mp.lower_bound(x);--it;
    		for(int i=max(l,it->se+y);;i+=y){
    			pii cur=ask(i,i);
    			mp[cur.fi]=i;
    			if(cur.fi==x)break;
    		}
    	}int pos=mp[x];
    	pii L=ask(pos-y+1,pos);
    	pii R=ask(pos,pos+y-1);
    	int lb=0,rb=0;
    	if(L.fi==x)lb=1+pos-L.se,rb=lb+y-1;
    	else lb=pos+R.se-y,rb=lb+y-1;
    	for(int i=lb;i<=rb;i++)a[i]=x;
    	solve(l,lb-1);solve(rb+1,r);
    }
    int main(){
    	mp[0]=0;
    	n=read();solve(1,n);
    	printf("! ");
    	for(int i=1;i<=n;i++)
    		printf("%d ",a[i]);puts("");
    	fflush(stdout);
        return 0;
    }
    
  • 相关阅读:
    我们如何监视所有 Spring Boot 微服务?
    如何使用 Spring Boot 实现异常处理?
    如何使用 Spring Boot 实现分页和排序?
    如何集成 Spring Boot 和 ActiveMQ?
    如何实现 Spring Boot 应用程序的安全性?
    Spring Boot 中的监视器是什么?
    如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?
    Spring 和 SpringBoot 有什么不同?
    Spring Boot 有哪些优点?
    如何在不使用BasePACKAGE过滤器的情况下排除程序包?
  • 原文地址:https://www.cnblogs.com/syzf2222/p/15836804.html
Copyright © 2020-2023  润新知