zoukankan      html  css  js  c++  java
  • CF1119 Global Round 2

    CF1119A Ilya and a Colorful Walk

    • 这题二分是假的.. (1,2,1,2,1) 有间隔为 (3) 的,但没有间隔为 (2) 的.开始被 (hack) 了一次.后来改过来了.
    • 我的做法:扫一遍,记录每个颜色第一次出现的位置,并存入一个 (set) 中,若当前颜色未出现,就更新位置,存入 (set) ,否则将那个位置删除.然后查询一次 (set) 中最小元素.最后再把那个位置插入回去.
    • 官方题解:最远距离两个端点中一定包含 (1)(n) 中至少一个.若 (c_i ot =c_j,1<i<j<n) ,那么如果 (c_1,c_n) 不同,那么端点可以直接选 (1,n) ,否则若 (c_1=c_n) ,那么 (c_1 ot = c_j,c_i ot =c_n) 至少有一个成立,端点也会拓展到边界上.
    • 找与 (1​) 颜色不同的点与 (1​) 的最远距离,与 (n​) 颜色不同的点与 (n​) 的最远距离取 (max​) 即可.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    int n;
    const int MAXN=3e5+10;
    int c[MAXN];
    int check(int x)
    {
    	for(int i=1;i+x<=n;++i)
    		if(c[i]!=c[i+x])
    			return 1;
    	return 0;
    }
    int pos[MAXN];
    set<int> s;
    int main()
    {
    	n=read();
    	s.insert(n+1);
    	int ans=0;
    	for(int i=1;i<=n;++i)
    		{
    			int x=read();
    			int y=pos[x];
    			if(y)
    				s.erase(y);
    			int p=*s.begin();
    			ans=max(ans,i-p);
    			if(!pos[x])
    				pos[x]=i;
    			if(pos[x])
    				s.insert(pos[x]);
    		}
    	cout<<ans<<endl;
    	return 0;
    }
    

    CF1119B Alyona and a Narrow Fridge

    • 这题二分是真的,能放下前 (k) 个显然就能放下前 (k-1) 个嘛.于是二分答案,判断放前 (k) 个是否可行.这里贪心放,最大的和次大的放在一起,后面同理,排序后两个两个放下来即可.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    #define mp make_pair
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    int n,h;
    const int MAXN=1e3+10;
    int a[MAXN];
    int b[MAXN],tp=0;
    bool check(int k)
    {
    	for(int i=1;i<=k;++i)
    		b[i]=a[i];
    	sort(b+1,b+1+k);
    	int f=0,rs=h;
    	for(int i=k;i>=1;--i)
    	{
    		if(!f)
    		{
    			rs-=b[i];
    			if(rs<0)
    				return false;
    		}
    		f^=1;
    	}
    	return true;
    }
    int main()
    {
    	n=read(),h=read();
    	int s=0;
    	for(int i=1;i<=n;++i)
    		a[i]=read();
    	int L=1,R=n;
    	int ans=0;
    	while(L<=R)
    	{
    		int mid=(L+R)>>1;
    		if(check(mid))
    			ans=mid,L=mid+1;
    		else
    			R=mid-1;
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

    CF1119C Ramesses and Corner Inversion

    • 注意到这个翻转操作只改变四个角落的值,不会改变每一行每一列的 (1) 个数的奇偶性.
    • 那么若有一行/列 (A,B) 奇偶性不同,显然不合法.
    • 否则?对于每个不同的位置 ((x,y)) ,我们都选择它作为右下角, ((1,1)) 作为左上角进行操作.这样所有不同的地方都被修改到一样了,而 (A,B) 每一行/列奇偶性都相同,多修改的部分 ((1,1),(1,y),(1,x)) 恰好抵消, (A) 就变成了 (B) ,所以一定合法.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    const int MAXN=512;
    int a[MAXN][MAXN],b[MAXN][MAXN];
    int main()
    {
    	int n=read(),m=read();
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			a[i][j]=read();
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			b[i][j]=read();
    	for(int i=1;i<=n;++i)
    	{
    		int s1=0,s2=0;
    		for(int j=1;j<=m;++j)
    			s1+=a[i][j],s2+=b[i][j];
    		s1&=1,s2&=1;
    		if(s1!=s2)
    			return puts("No"),0;
    	}
    	for(int j=1;j<=m;++j)
    	{
    		int s1=0,s2=0;
    		for(int i=1;i<=n;++i)
    			s1+=a[i][j],s2+=b[i][j];
    		s1&=1,s2&=1;
    		if(s1!=s2)
    			return puts("No"),0;
    	}
    	puts("Yes");
    	return 0;
    }
    

    CF1119D Frets On Fire

    • 题面太鬼畜了...建议直接看 (Formally) 那一段.
    • 首先容易发现, (s) 数组的顺序对答案是不影响的.所以我们可以先将 (s) 从小到大排序.
    • 每次询问 ((l,r)) ,对于每个 (s_i) ,它所贡献的数就是 ([s_i+l,s_i+r]) 这一段,那么就等价于给了 (n) 条长度一样的线段,问覆盖的长度.
    • 可以考虑用整个区间 ([s_1+l,s_n+r]) 的长度减去中间没有覆盖到的部分.容易发现这样的部分只可能出现在两条相邻线段之间,可以直接用 (max(s_{i+1}+l-s_i-r-1,0)) 来计算.那么这次询问的答案就是

    [ans=s_n+r-s_1-l+1-sum_{i=1}^{n-1} max(s_{i+1}+l-s_i-r-1,0)\ =s_n+r-s_1-l+1-sum_{i=1}^{n-1} max(s_{i+1}-s_i-(r-l+1),0) ]

    • (b_i=s_{i+1}-s_i) ,将 (b_i) 排序后记录一下前缀和,询问时二分找出 (b_igeq r-l+1) 的第一个位置,只算后面的部分即可.时间复杂度 (O(nlogn+qlogn)) .
    #include<bits/stdc++.h>
    #define inf (1e18)+10
    using namespace std;
    typedef long long ll;
    inline ll read()
    {
    	ll out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    const int MAXN=1e6+10;
    ll n,a[MAXN];
    ll b[MAXN];
    ll sum[MAXN];
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)
    		a[i]=read();
    	sort(a+1,a+1+n);
    	for(int i=1;i<n;++i)
    		b[i]=a[i+1]-a[i];
    	sort(b+1,b+n);
    	for(int i=1;i<n;++i)
    		sum[i]=sum[i-1]+b[i];
    	int Q=read();
    	while(Q--)
    	{
    		ll l=read(),r=read();
    		ll s=r-l+1;
    		ll ans=a[n]+r-a[1]-l+1;
    		if(s>b[n-1])
    		{
    			cout<<ans<<' ';
    			continue;
    		}
    		int p=lower_bound(b+1,b+n,s)-b;	
    		ans-=sum[n-1]-sum[p-1];
    		ans+=1LL*(n-p)*s;
    		cout<<ans<<' ';
    	}
    	return 0;
    }
    

    CF1119E Pavel and Triangles

    • 可以发现, (2^i+2^j>2^k,ileq j leq k) 有解,只可能是 (ileq j,k=j) .
    • 那么直接贪心选,每次读入了 (x)(2^i) ,就先尝试用两个 (i) 与之前剩下的任意一个 (j) 配对,再尝试 ((i,i,i)) 三个配对,再将剩余的留着,后面再用.
    • 为什么要先尝试 ((i,i,i)) 三个配对呢?因为如果不进行这一步,它在之后的步骤中每想形成一个三角形就还需要 (2) 个木棍构成 ((i,j,j)) 的形式,显然劣于 ((i,i,i)) 直接配对.
    • 官方证明.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    const int MAXN=3e5+10;
    int a[MAXN];
    ll ans=0,rest=0;
    int main()
    {
    	int n=read();
    	for(int i=1;i<=n;++i)
    		{
    			int x=read();
    			ll p=min(1LL*x/2,rest);
    			ans+=p;
    			rest-=p;
    			x-=p*2;
    			ans+=x/3;
    			x%=3;
    			rest+=x;
    		}
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    luoguP2939 [USACO09FEB]改造路Revamping Trails
    出题
    数字游戏
    统一异常处理
    数据验证
    拦截器
    数据绑定和表单标签库
    类型转换和格式化
    Spring MVC入门
    4springboot:日志(下)
  • 原文地址:https://www.cnblogs.com/jklover/p/10664164.html
Copyright © 2011-2022 走看看