• Educational Codeforces Round 111 (Rated for Div. 2)


    一些感想

    感觉最近很不在状态,整场比赛不知道在干什么... 连 ( m C) 这么水的暴力也没看出来...

    真的应该改改自己想完就开码的坏习惯,不能因为是虚拟赛就这么随意。

    ( ext{C - Manhattan Subarrays})

    解法

    考虑 (d(p,r)=|x_p-x_r|+|y_p-y_r|)(d(p,q)+d(q,r)=(|x_p-x_q|+|x_q-x_r|)+(|y_p-y_q|+|y_q-y_r|))

    显然我们有 (|x_p-x_r|ge |x_p-x_q|+|x_q-x_r|)(y) 同理。

    所以当 (d(p,r)=d(p,q)+d(q,r)) 时必然有 (|x_p-x_r|= |x_p-x_q|+|x_q-x_r|)(y) 同理。而不会有一个大于一个小于的情况。

    转化一下式子,发现实际上 "( ext{bad triple})" 就是下标 (i<j<k),有 (a_ile a_jle a_k)(a_ige a_jge a_k)

    "( ext{good array})" 长度不超过 (4),汝可模拟得之。

    简单证明一下。首先,可能的长度为 (3) 的 "( ext{good array})" 只有两种情况(情况不同主要的是相对位置不同,对称的是等价的):

    1. ---
            ---
         ---
      
    2.       ---
      ---
         ---
      

    对于 情况 1 没有长度为 (4) 的 "( ext{good array})";而 情况 2 可以在 (i,k)(i,j) 中再插入一段,但这样必定又构造出 情况 1,所以结论得证。

    代码

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    #define print(x,y) write(x),putchar(y) 
    
    template <class T> inline T read(const T sample) {
        T x=0; int f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    template <class T> inline void write(const T x) {
        if(x<0) return (void) (putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    
    const int maxn=2e5+5;
    
    int n,a[maxn];
    
    bool ok(int l,int r) {
    	if(r-l+1<=2) return 1;
    	if(r-l+1==3) 
    		return !((a[l]<=a[l+1] and a[l+1]<=a[r])or
    				(a[l]>=a[l+1] and a[l+1]>=a[r]));
    	for(int i=l;i<=l+1;++i)
    		for(int j=i+1;j<r;++j)
    			for(int k=j+1;k<=r;++k)
    				if((a[i]<=a[j] and a[j]<=a[k])or
    				(a[i]>=a[j] and a[j]>=a[k])) 
    					return 0;
    	return 1;
    	
    }
    
    int main() {
    	int ans,T=read(9);
    	for(int o=1;o<=T;++o) {
    		n=read(9); ans=0;
    		for(int i=1;i<=n;++i)
    			a[i]=read(9);
    		for(int i=1;i<=n;++i) {
    			for(int j=i;j<=min(i+3,n);++j)
    				if(ok(i,j)) ++ans;
    				else break;
    		}
    		print(ans,'
    ');
    	}
    	return 0;
    } 
    

    ( ext{E - Stringforces})

    解法

    (kle 17),我们考虑状压。一个基本的转化是二分最大值 (x),那么就只用检查每种字母是否均有长度为 (x) 的段。

    (dp_s) 为满足的字母集合为 (s) 需要的最短前缀。考虑转移,需要计算在位置 (i) 之后构造出字母 (j) 的长度为 (x)最靠前 段的右端点。

    直接在 (dp_s) 转移时计算此信息会导致复杂度飙升,其实可以直接预处理,令它为 (pos_{i,j})

    对于 (pos_{i,j}) 的转移,显然如果 ([i+1,i+x]) 中没有其他字母就可以更新为 (i+x),否则直接继承 (pos_{i+1,j})

    关于判定 ([i+1,i+x]) 中是否有其他字母,可以将字母正反都枚举一遍,具体可以看看代码;还可以直接对每个字母做一个出现次数的后缀和,再统计所有字母出现次数后缀和。反正都是 (mathcal O(nk)) 的。

    代码

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    #define print(x,y) write(x),putchar(y) 
    
    template <class T> inline T read(const T sample) {
        T x=0; int f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    template <class T> inline void write(const T x) {
        if(x<0) return (void) (putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    
    const int maxn=2e5+5;
    
    int n,k,pos[maxn][18];
    int dp[1<<17],las[18];
    char s[maxn];
    
    bool ok(int mid) {
    	for(int i=0;i<k;++i) 
    		las[i]=n+1,
    		pos[n][i]=n+1;
    	for(int i=n-1;i>=0;--i) {
    		if(s[i]^'?') 
    			las[s[i]-'a']=i+1;
    		int cur=n+1;
    		for(int j=0;j<k;++j) {
    			pos[i][j]=(i+mid<cur?i+mid:pos[i+1][j]);
    			cur=min(cur,las[j]);
    		}
    		cur=n+1;
    		for(int j=k-1;j>=0;--j) {
    			if(i+mid>=cur)
    				pos[i][j]=pos[i+1][j];
    			cur=min(cur,las[j]);
    		}
    	}
    	for(int s=0;s<(1<<k);++s) dp[s]=n+1;
    	dp[0]=0;
    	for(int s=0;s<(1<<k);++s)
    		if(dp[s]<n)
    			for(int i=0;i<k;++i)
    				if(!(s>>i&1))
    					dp[s|(1<<i)]=min(dp[s|(1<<i)],pos[dp[s]][i]);
    	return dp[(1<<k)-1]<=n;
    }
    
    int main() {
    	n=read(9),k=read(9);
    	scanf("%s",s);
    	int l=0,r=n,mid;
    	while(l^r) {
    		mid=l+r+1>>1;
    		if(ok(mid))
    			l=mid;
    		else r=mid-1;
    	}
    	print(l,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    html5表单pattern属性配合正则验证电话和手机号码
    关于a href传参的中文乱码问题
    jq点击事件改变全局变量
    a标签带参页面跳转并在跳转页面接收参数
    json字段不存在,手动添加键值对
    各种类型相互转换
    Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value '�й���׼ʱ��' is unrecognized or r
    微信公众号之微信登录失败,redirect_uri域名与后台配置不一致,错误代码10003
    前后端数据json交换的问题
    jQuery EasyUI 的editor组件使用
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15021842.html
Copyright © 2020-2023  润新知