首页 > 其他分享 >Living-Dream 系列笔记 第15期

Living-Dream 系列笔记 第15期

时间:2024-03-09 12:36:57浏览次数:34  
标签:Living 15 1000031 int mid long 1531 Dream check

模拟赛爆炸祭。

T1

把所有连通块依次求出,若某个连通块的数量已经出现过,则说明它与以前的连通块属于同一星系,直接将星系大小加上连通块大小并取 \(\max\);否则将星系数量 \(+1\)。

#include<bits/stdc++.h>
#define int long long
using namespace std;

int n,m;
int ans=-1e9,num,sum;
int g[100031];
int dx[]={-1,1,0,0,-1,-1,1,1},dy[]={0,0,-1,1,-1,1,-1,1};
bool vis[1531][1531],v[1531];
char a[1531][1531];

void dfs(int x,int y){
	num++,vis[x][y]=1;
	for(int i=0;i<8;i++){
		int xx=x+dx[i],yy=y+dy[i];
		if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]&&a[xx][yy]=='*')
			dfs(xx,yy);
	}
}

signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>a[i][j];
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]=='*'&&!vis[i][j]){
				num=0;
				dfs(i,j);
				if(!v[num]) sum++,v[num]=1;
				g[num]+=num; 
			}
		}
	}
	for(int i=1;i<=100000;i++) ans=max(ans,g[i]);
	cout<<sum<<' '<<ans;
	return 0;
}

T2

一眼二分。在 check 函数中遍历整个数列,若没超过最大和就不断累加数列元素,否则将段数 \(+1\),最后判断是否能分成 \(\le m\) 段即可。

注意段数最少为 \(1\),且左边界最小为 \(\max\{a_i\}\)。

#include<bits/stdc++.h>
#define int long long
using namespace std;

int n,m,a[100031],maxi=-1e9;

bool check(int x){
	int sum=0,cnt=1;
	for(int i=1;i<=n;i++){
		if(sum+a[i]<=x) sum+=a[i];
		else cnt++,sum=a[i];
	}
	return cnt<=m;
}

signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i],maxi=max(maxi,a[i]);
	int l=maxi-1,r=1e9+1;
	while(l+1<r){
		int mid=(l+r)>>1;
		if(check(mid)) r=mid;
		else l=mid;
	}
	cout<<r;
	return 0;
}

T3

因为天数具有单调性,所以仍考虑二分需要修改的那一天 \(mid\)。

check 函数中循环 \(1 \sim mid\) 天,不断使用差分数组进行区间减操作,最后求出前缀和数组,若其中某个元素 \(<0\) 则返回 true,否则返回 false。注意先将前缀和数组清空。

#include<bits/stdc++.h>
#define int long long
using namespace std;

int n,m;
int a[1000031],d[1000031],s[1000031],t[1000031];
int diff[1000031],sum[1000031];

bool check(int x){
    //cout<<s[x]<<'\n';
    memset(sum,0,sizeof(sum));
    for(int i=1;i<=n;i++) diff[i]=a[i]-a[i-1];
    for(int i=1;i<=x;i++)
		diff[s[i]]-=d[i],diff[t[i]+1]+=d[i];
	for(int i=1;i<=n;i++){ 
	    sum[i]=sum[i-1]+diff[i];
	    if(sum[i]<0) return true;
	}
	return false;
}

signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) 
	    cin>>a[i],diff[i]=a[i]-a[i-1];
	for(int i=1;i<=m;i++)
	    cin>>d[i]>>s[i]>>t[i];
	int l=0,r=n+1;
	//cout<<check(2)<<' '<<check(1)<<'\n';
	while(l+1<r){
	    int mid=(l+r)>>1;
	    //cout<<mid<<'\n';
	    if(check(mid)) r=mid;
	    else l=mid;
	}
	if(r==n+1) cout<<0;
    else cout<<-1<<'\n'<<r;
	return 0;
}

T4

原题,略过。

标签:Living,15,1000031,int,mid,long,1531,Dream,check
From: https://www.cnblogs.com/XOF-0-0/p/18062511

相关文章

  • Living-Dream 系列笔记 第11期
    本期主要讲解与上期相同内容(雾。例题T1在整个矩阵外加一圈\(0\),使得包围圈外的\(0\)形成一整个连通块。求出这个连通块并标记为\(1\),然后输出即可。#include<bits/stdc++.h>usingnamespacestd;intn;intdx[]={-1,0,1,0},dy[]={0,1,0,-1};inta[31][31],g[31][31];......
  • Living-Dream 系列笔记 第12期
    本期主要讲解一维前缀和技巧。知识点我们令\(a_i\)表示原数组的第\(i\)个元素,则\(sum_i\)表示\(a_i\)前\(i\)个元素之和,即:\[sum_i=\sum^{i}_{j=1}a_j\]我们知道,\(a\)数组前\(i\)个元素的和\(=\)前\(i-1\)个元素的和\(+a_i\)。于是便可得到\(sum\)数组的......
  • Living-Dream 系列笔记 第13期
    本期主要讲解二维前缀和。知识点我们令\(a_{i,j}\)表示原数组,则\(sum_{i,j}\)为\(a\)的二维前缀和数组。根据容斥原理,得到递推式:\[sum_{i,j}=sum_{i-1,j}+sum_{i,j-1}-sum_{i-1,j-1}+a_{i,j}\]二维前缀和适用于求静态矩阵的子矩阵元素和。若我需要求一个左上角坐标为......
  • Living-Dream 系列笔记 第10期
    本期主要讲解进阶\(\text{DFS}\)。知识点\(\text{DFS}\)求解连通块问题:定义:若一个点集中的所有点都能互达,且与集合外的点无法互达,则称此点集为一个连通块。考查方式:求连通块数量/大小/周长。例题T1在\(\text{DFS}\)函数中传入参数\(x\)和\(str\),分别表示......
  • Living-Dream 系列笔记 第8期
    本期主要讲解的与上期相同。例题T1上课的时候调这个题感觉要吐了\(qwq\)。。。首先读入\(n\)行字符串,可以采取忽略中间无关单词的方式来直接读取\(X\)和\(Y\)。将所有名字存入\(a\)数组,对\(a\)数组按字典序排序后就可以开始\(\text{DFS}\)了,这里建议使用next_pr......
  • Living-Dream 系列笔记 第9期
    模拟赛掉大分(悲T1板子,不讲。T2首先很明显这题是个去重全排列。和模板的区别就是加了一个\(sum\)参数记录目前已经放了几个苹果。当\(x=n+1\)时若\(sum=m\),则更新答案。同时加入一个剪枝:若在搜索过程中\(sum>m\),则直接return结束搜索。#include<bits/stdc++.h>usi......
  • Living-Dream 系列笔记 第6期
    模拟赛。寄。T1对于每次询问,二分查找数组中对应值的原下标即可,因此需要用结构体存储原始数据和原始下标。这当然是比较麻烦的做法。另一种做法则是开一个map替代桶来存储数组中每个元素的下标,对于每个询问输出即可。另外值得注意的是,本题默认询问之间相互独立。时间复杂度......
  • Living-Dream 系列笔记 第7期
    本期主要讲解深度优先搜索\(\text{DFS}\)。知识点种类:全排列。可以想象为填格子。去重全排列,即组合。时间复杂度均为\(O(n!)\)。\(\text{DFS}\)题的特征:求方案总数/最值。数据范围极小(一般\(n\le20\))。无法直接暴力枚举(因为循环嵌套层数不确定)。......
  • Living-Dream 系列笔记 第4期
    本期主要讲解二分答案。知识点使用场景:最小值最大化,或最大值最小化。在限制条件下找最值。与二分查找的区别:L、R均为答案,而非下标。输出:最大化输出L,反之输出R。例题T1二分\(M\)的值,边界为\(L=-1,R=\max{\{a_i\}}\)。每次枚举到一个\(mid\)就对于每个......
  • Living-Dream 系列笔记 第5期
    本期主要讲解二分答案的进阶。例题T1二分需要的秒数,在check函数中对于每件衣服,若其在\(x\)秒内无法自然晒干,则使用烘干机,并令\(sum\)加上使用烘干机的秒数,最后判断\(sum\)是否\(\lex\)即可。\(Trick\):二分边界需要按数据范围尽可能开大,不能开小了。#include<bits/......