首页 > 其他分享 >Codeforces Round 906 (Div. 2) E1

Codeforces Round 906 (Div. 2) E1

时间:2024-04-24 20:00:50浏览次数:21  
标签:这个 906 覆盖 read ll 答案 区间 Div E1

时隔了不知道多久的补题。两个月吧,这是可是寒假的比赛。

但是补题的时候还是遇到了很多问题。
很重要的有一些地方能够简化,一些条件没有充分的利用上,导致了我很多地方考虑的太复杂。
这些能够简化的地方全部利用上我觉得才算是写出来了这道题目,否则这题会复杂到我赛时写不完,而且特别长,很容易就调不出来的程度。
这题的话,则是对使用次数少的时候的可供选择的区间的特殊性不够敏感,事实上只被覆盖过一次的区间是非常特殊的。

这个问题很明显是分为两种情况的,一种是我选择的两个区间是互不相交的,一种是他们之间有相交的区间。 很明显除了这两个没有其他情况。

我当时的第一个想法就是找到前两个分别删去后能够产生的价值最大的区间,然后删掉他们,这就是答案。
然后,离谱的事情来了。
假如这两个区间相交,那他们产生的价值不就是不合法的吗,这样就是错的,所以要符合我们预设的要求,我们应该去对每个点维护只覆盖了这个点之前的位置和之后的位置的区间假如被删去一个所能产生的最大的价值,这样才是符合我们的要求的。
代码复杂程度++。
但是,真的有必要吗?
假如这是对的,那我们的第二个类型的答案要如何维护?
枚举每个区间对,然后尝试删除?
直接T掉,\(O(n^2)\)想都不用想。
然后我顺着这个思路往下,尝试区间排序然后找相邻区间,很高兴的发现这个没有正确性。
而正解就是用一个set来维护,统计当前这个位置已经被覆盖了几次。
假如这个位置被覆盖了两次,那就尝试删去这两个区间,统计答案。
假如只覆盖了一次,是没有必要的。因为这个位置如果是答案,那就有两种答案,一种是覆盖这个位置的区间会再和至少两个区间重合
这种情况下这个区间所覆盖的所有区域可能都不会出现只被覆盖两次的情况,也就是不会去尝试删去这个区间。但是,这个其实已经被考虑过了,就在我们最上面的第一个尝试中。但是如果是完全按照上面所说的第一个情况,也就是排除了选择的两个区间相交的情况,那就不可做了。
考虑这样的三个区间:[1,10],[5,6],[5,6]
这是一个很好的反例,没有任何一个位置被覆盖了三次,但是答案就是删去[1,10]。这个答案是在第一种情况中需要被统计的。
所以我们统计答案的答案,其实是应该分为这样两种:1.这个区间中没有被覆盖两次的位置,2.这个区间中有被覆盖两次的位置。
这才是最简单的统计。

这个思路的产生可以来自简化第一种答案的统计。但是其实有点不现实,写题的思路来自计算当前情况的答案较为简单的方法。。
计算这个答案简单,总体写起来就简单吗?这个贪心可不成立。
还是都试试,都想一下再选择。

主要就是不知道怎么选。很容易钻牛角尖,进了这思路,出不来了。
但是很多时候就是要退出来想想的。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
	ll a=0,b=1;char c=getchar();
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
	return a*b;
}
ll n,m,k;
ll l[200010],r[200010],An[200010];
ll a[200010];
ll sum[200010][5];
vector<ll> seg[200010];
int main()
{
	ll T=read();
	while(T--)
	{
		n=read(),m=read(),k=read();
		for(ll i=1;i<=n;i++)seg[i].clear(),a[i]=0;
		for(ll i=1;i<=m;i++)
		{
			l[i]=read(),r[i]=read();
			a[l[i]]++;a[r[i]+1]--;
			seg[l[i]].push_back(i);
			seg[r[i]+1].push_back(-i);
		}
		ll ans=0;
		for(ll i=1;i<=n;i++)
		{
			sum[i][0]=sum[i-1][0]+a[i];
			if(sum[i][0]==1)sum[i][1]=1;
			else sum[i][1]=0;
			if(sum[i][0]==0)ans++;
			if(sum[i][0]==2)sum[i][2]=1;
			else sum[i][2]=0;
		}
		for(ll i=1;i<=n;i++)
		{
			sum[i][3]=sum[i-1][3]+sum[i][1];
			sum[i][4]=sum[i-1][4]+sum[i][2];
		}
		ll Max1=0,Max2=0;
		for(ll i=1;i<=m;i++)
		{
			An[i]=sum[r[i]][3]-sum[l[i]-1][3];
			if(An[i]>=Max1)
			{
				Max2=Max1;
				Max1=An[i];
			}
			else
			if(An[i]>Max2)Max2=An[i];
		}
		ll Mans=Max1+Max2;
//		cout<<Mans<<endl;
		set<ll> s;
		for(ll i=1;i<=n;i++)
		{
			for(ll j=0;j<seg[i].size();j++)
			{
				if(seg[i][j]<0)s.erase((-seg[i][j]));
				else s.insert((seg[i][j]));
			}
//			cout<<s.size()<<' ';
			if(s.size()==2)
			{
				ll fir=*s.begin(),sec=*s.rbegin();
				ll L=min(l[fir],l[sec]),MidL=max(l[fir],l[sec]),MidR=min(r[fir],r[sec]),R=max(r[fir],r[sec]);
				Mans=max(Mans,sum[MidL-1][3]-sum[L-1][3]+sum[R][3]-sum[MidR][3]+sum[MidR][4]-sum[MidL-1][4]);/*
				if(i==8)
				{
					cout<<L<<' '<<MidL<<' '<<MidR<<' '<<R;
					cout<<endl<<sum[MidL-1][3]-sum[L-1][3]<<' '<<sum[R][3]-sum[MidR][3]<<' '<<sum[MidR][4]-sum[MidL-1][4]<<endl;
				}*/
			}
		}
//		cout<<endl;
		cout<<Mans+ans<<endl;
	}
	return 0;
}

标签:这个,906,覆盖,read,ll,答案,区间,Div,E1
From: https://www.cnblogs.com/HLZZPawa/p/18156202

相关文章

  • 基于DE1-SOC的Nios V工程——my_first_niosv
    一、NiosV简介目前Intel推出了三款Nios®V处理器(图片来自Intel官网): (点击图可放大)  这里面功能最强的是NiosV/g,用户可根据实际需求选择对应的软核。 截图来自Nios®V嵌入式处理器设计手册:  二、开发工具下载目前Quartus22.1及以上版本都支持NiosV了,本文以......
  • CRound927__Div3__C
    这道题涉及到两个部分,先是逆向思维,正着做一定会无比困难,而倒过来想就会好做,也比较难想到逆向思维,见识又少了,倒着思考就得先找到最后一个移除的元素include<bits/stdc++.h>usingnamespacestd;defineforn(i,n)for(inti=0;i<int(n);i++)intmain(){intt;cin......
  • 给定两个数x和y(长度相等),让它们可以交换各个位上的数字(位对应交换),求让两数乘积最大的
    如题,给出x=73,y=31,如何让两数乘积最大?位数定义:各个位上的数字例73,位数有7,3当前,只有一种交换策略,x=71,y=33,发现交换以后有:x+y=x'+y',如果抽象成求最大面积就好办了,可能一下想不到,还得多积累经验,不是你不知道是你想不到是你见得少,没见识...当是正方形的时候面积最大小学......
  • Codeforces Round 940 (Div. 2) and CodeCraft-23
    A.Stickogon#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;usingi64=longlong;#defineinti64usingvi=vector<int>;constintN=3e5,mod=1e9+7;voidsolve(){ vicnt(101); intn; cin>>n; for(i......
  • Codeforces Round 892 (Div. 2) 复盘
    A没啥好说的。B也是,很简单的贪心。但是AB都因为读题导致的理解误差wa了一发。哎,读题读错,只能说英语还得练。C,赛时没做出来,后面的也是。这个题目其实思路已经有了,cf的这种题,还放在C题,那就是很明显那种能打标看出规律的东西。就算知道了是打表能看出来的,我懒得写暴力,所以就一直......
  • img case1
    <body><divclass="slider"><divclass="slider-wrapper"><imgsrc="./test1.png"alt=""/><divclass="box">X</div><......
  • Codeforces Round 940 (Div. 2) and CodeCraft-23
    CodeforcesRound940(Div.2)andCodeCraft-23前四题难度适中,总体还算不错,我想想都能做。E题考察威尔逊和质数筛前缀和算贡献。F题是数据结构,据说很版,还没补。A题:题意:给出n个木棍,最多组成多少个多边形Solution:统计各长度木棍的数量,全部贪心成三角形voidsolve(){ cin>>n;......
  • Codeforces 1863F Divide, XOR, and Conquer
    记\(s_{l,r}=\oplus_{i=l}^ra_i\)。考虑到这个相当于是\([l,r]\)内分裂区间,可以考虑区间\(\text{DP}\)。即记\(f_{l,r}\)为\([l,r]\)区间是否能被遍历到。转移考虑对于\([l,r]\),考虑在已知的条件下(\(len\ger-l+1\))\([l,r]\)是否合法。即到这个状态......
  • 在页面中居中一个div
    如何在一个页面中居中一个div?方法一:<div    style="width:100px;    height:100px;    background:red;    position:absolute;    top:50%;    left:50%;    margin:-50px00-50px;">  </div>......
  • Codeforces Round 940 (Div. 2) and CodeCraft-23 (补题中的小白)
    A.Stickogon思路:Code:#include<bits/stdc++.h>usingnamespacestd;voidsolve(){intn;cin>>n;map<int,int>mp;for(inti=1,x;i<=n;i++){cin>>x;mp[x]++;}intans=0;f......