首页 > 其他分享 >近期总结

近期总结

时间:2024-09-26 21:45:57浏览次数:1  
标签:总结 int 线段 近期 long ans 区间 define

一些近期的模拟赛,被暴打。

9.19 D

\(m\) 个部落,\(n\) 个洞穴。一开始每个洞穴被 \(a_i\) 占领,或无人。

有两种操作:

  1. 给出 \(l,r,k\)。区间 \([l,r]\) 更改为 \(k\) 占领。

  2. 给出 \(l,r,k\)。区间 \([l,r]\) 的每个洞穴出现价值为 \(k\) 的宝物,由占领该洞穴的部落获得,若无部落占领,则由下一个占领的部落获得。

求最终各个部落获得的宝物价值总和。

想了一会在线,发现不是很可做。反着做也想了好一会,鉴定为对数据结构的使用不够熟练。

想到反着做就基本结束了其实,原本的 1 操作就是 \(ans_k\) 加上区间和,然后区间归零。

2 操作就是一个简单的区间加。

懒得打了于是 Copy 的线段树 2,区间归零就是区间乘 \(0\)。

#include<bits/stdc++.h>
#pragma GCC optimize(2,3,"Ofast","inline")
#define int long long
using namespace std;
const int N=5e5+10;
int n,m,q;
int c[N],ans[N];
struct node
{
	int op,l,r,x;
}a[N];
struct ccf
{
	int l,r,num,la1,la2;
}f[N<<2];
void build(int k,int l,int r)
{
	f[k].l=l,f[k].r=r,f[k].la1=1,f[k].la2=0;
	if(l==r)return ;
	int mid=(l+r)/2;
	build(k*2,l,mid);
	build(k*2+1,mid+1,r);
}
void pushdown(int k)
{
	if(f[k].la1!=1||f[k].la2)
	{
		int l=k*2,r=k*2+1;
		f[l].num*=f[k].la1;
		f[l].num+=(f[l].r-f[l].l+1)*f[k].la2;
		f[r].num*=f[k].la1;
		f[r].num+=(f[r].r-f[r].l+1)*f[k].la2;
		f[l].la1*=f[k].la1;
		f[l].la2=f[l].la2*f[k].la1+f[k].la2;
		f[r].la1*=f[k].la1;
		f[r].la2=f[r].la2*f[k].la1+f[k].la2;
		f[k].la1=1,f[k].la2=0;
	}
}
void change(int k,int l,int r,int x,int y,int v,int op)
{
	if(l>y||r<x)return ;
	if(x<=l&&r<=y)
	{
		if(op==1)f[k].num*=v,f[k].la1*=v,f[k].la2*=v;
		else f[k].num+=(r-l+1)*v,f[k].la2+=v;
		return ;
	}
	pushdown(k);
	int mid=(l+r)/2;
	change(k*2,l,mid,x,y,v,op);
	change(k*2+1,mid+1,r,x,y,v,op);
	f[k].num=f[k*2].num+f[k*2+1].num;
}
int ask(int k,int l,int r,int x,int y)
{
	if(l>y||r<x)return 0;
	if(x<=l&&r<=y)return f[k].num;
	pushdown(k);
	int mid=(l+r)/2;
	return ask(k*2,l,mid,x,y)+ask(k*2+1,mid+1,r,x,y);
}
signed main()
{
	cin>>n>>m>>q;
	build(1,1,n);
	for(int i=1;i<=n;i++)
		scanf("%lld",&c[i]);
	for(int i=1;i<=q;i++)
		scanf("%lld%lld%lld%lld",&a[i].op,&a[i].l,&a[i].r,&a[i].x);
	build(1,1,n);
	for(int i=q;i>=1;i--)
	{
		if(a[i].op==1)
		{
			ans[a[i].x]+=ask(1,1,n,a[i].l,a[i].r);
			change(1,1,n,a[i].l,a[i].r,0,1);
		}
		else change(1,1,n,a[i].l,a[i].r,a[i].x,2);
	}
	for(int i=1;i<=n;i++)
		if(c[i])ans[c[i]]+=ask(1,1,n,i,i);
	for(int i=1;i<=m;i++)
		printf("%lld\n",ans[i]);
	return 0;
}

9.24 D

给出一个 \(n\) 个点,\(m\) 条边的有向图,求有多少个点集 \(S\) 满足,\(\forall i\in S\),若存在边 \((i,j)\),则 \(j\in S\)。同时点集 \(S\) 是连续的,即点的编号是连续的。

一眼顶针 \(O(n^2)\) 做法,枚举左右端点:

#include<bits/stdc++.h>
#define min(x,y) (x<y?x:y)
#define max(x,y) (x>y?x:y)
using namespace std;
const int N=3e5+10;
int n,m,ans;
int x[N],y[N];
vector<int>v[N];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		v[x].push_back(y);
	}
	memset(x,127,sizeof(x));
	for(int i=1;i<=n;i++)
		for(int k:v[i])
			x[i]=min(k,x[i]),y[i]=max(k,y[i]);
	for(int i=1;i<=n;i++)
	{
		int mi=1e9,ma=0;
		for(int j=i;j<=n;j++)
		{
			mi=min(mi,x[j]),ma=max(ma,y[j]);
			if(mi<i)break;
			if(ma<=j)ans++;
		}
	}
	cout<<ans;
	return 0;
}

然后就不会优化了,鉴定为不会用数据结构。

琢磨了一下午,但还是不会。场上切这题的人还不少。

问了大神,表示这是线段树应用模板。

对于每个 \(i\),它为左端点的贡献区间只有 \([i,r_i]\),这个 \(r_i\) 是可以二分在 \(\mathcal O(n)\) 内求出来的,那么可以在枚举右端点到 \(i\) 时丢到线段树上,然后在 \(r_i\) 时将它再拿出来。

同样的,它为右端点的贡献区间为 \([l_i,i]\),\(l_i\) 可以二分,然后在线段树求区间 \([l_i,i]\) 的和即可。

用 st 表预处理可以做到 \(\mathcal O(n\log n)\)。

线段树还是要多练啊!!!!!

#include<bits/stdc++.h>
#define int long long
#define min(x,y) (x<y?x:y)
#define max(x,y) (x>y?x:y)
using namespace std;
const int N=3e5+10,mod=1e9+7;
int n,m,ans;
int mi[N],ma[N],st[N][25],ts[N][25],f[N<<2];
vector<int>v[N];
int check(int l,int r)
{
	if(l>r)return 1e9;
	int k=log2(r-l+1);
	return min(st[l][k],st[r-(1<<k)+1][k]);
}
int chec(int l,int r)
{
	int k=log2(r-l+1);
	return max(ts[l][k],ts[r-(1<<k)+1][k]);
}
int find(int k)
{
	int l=k-1,r=n+1;
	while(l+1<r)
	{
		int mid=(l+r)/2;
		if(check(k,mid)>=k)l=mid;
		else r=mid;
	}
	return l;
}
int fin(int k)
{
	int l=0,r=k+1;
	while(l+1<r)
	{
		int mid=(l+r)/2;
		if(chec(mid,k)<=k)r=mid;
		else l=mid;
	}
	return r;
}
void add(int k,int l,int r,int x,int y)
{
	if(l==r)return f[k]+=y,void();
	int mid=(l+r)/2;
	if(x<=mid)add(k*2,l,mid,x,y);
	else add(k*2+1,mid+1,r,x,y);
	f[k]=f[k*2]+f[k*2+1];
}
int ask(int k,int l,int r,int x,int y)
{
	if(l>y||r<x)return 0;
	if(x<=l&&r<=y)return f[k];
	int mid=(l+r)/2;
	return ask(k*2,l,mid,x,y)+ask(k*2+1,mid+1,r,x,y);
}
signed main()
{
	memset(mi,127,sizeof(mi));
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%lld%lld",&x,&y);
		mi[x]=min(mi[x],y);
		ma[x]=max(ma[x],y);
	}
	for(int i=1;i<=n;i++)
	{
		if(!ma[i])ma[i]=i;
		st[i][0]=mi[i];
		ts[i][0]=ma[i];
	}
	for(int j=1;j<=20;j++)
		for(int i=1;i+(1<<j-1)<=n;i++)
			st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]),
			ts[i][j]=max(ts[i][j-1],ts[i+(1<<j-1)][j-1]);
	for(int i=1;i<=n;i++)
		if(mi[i]>=i)v[find(i)+1].push_back(i);
	for(int i=1;i<=n;i++)
	{
		if(mi[i]>=i)add(1,1,n,i,1);
		for(int j:v[i])
			add(1,1,n,j,-1);
		ans+=ask(1,1,n,fin(i),i);
	}
	cout<<ans%mod;
	return 0;
}

标签:总结,int,线段,近期,long,ans,区间,define
From: https://www.cnblogs.com/XuFromGD-FS/p/18434482/NOIP

相关文章

  • 9.24每日总结
    微服务拆分作业参考依赖user-service的pom.xml文件内容如下:<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xs......
  • 9.26每日总结
    给出SpringbootCloud的server:port:8084spring:application:name:user-serviceprofiles:active:devdatasource:url:jdbc:mysql://${hm.db.host}:3306/hm-user?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=......
  • 9.25每日总结 OpenFeign
    OpenFeign利用Nacos实现了服务的治理,利用RestTemplate实现了服务的远程调用。但是远程调用的代码太复杂了:而且这种调用方式,与原本的本地方法调用差异太大,编程时的体验也不统一,一会儿远程调用,一会儿本地调用。用到OpenFeign组件了。其实远程调用的关键点就在于四个:请求方式......
  • 万元购车平台源码开发总结与关键技术解析
    1.需求分析· 市场与用户调研:首先明确市场需求,了解用户群体(如购车者、经销商、平台管理者等)的具体需求。· 功能定义:确定系统需要支持的功能,如用户注册登录、车辆信息展示、公排规则设定、订单管理、支付接口集成、数据分析与报表等。· 非功能性需求:考虑系统的性能、可扩展性......
  • 网页设计第三章总结
    3.1表格概述表格是网页中的一个重要容器元素,可包含文字和图像。3.1.1表格的结构表格是由行和列组成的二维表,而每行又由一个或多个单元格组成,用于放置数据或其他内容。表格中的单元格是行与列的交叉部分,是组成表格的最基本单元。单元格的内容是数据,也称数据单元格。数据单元......
  • 9.26总结
    省流:死了T1由乃的差分分情况讨论。x<0最简单的情况,只需要升序输出即可。x=0其实就是:零不能放最前面,连续两个不一样,先把第一个输出完然后用排序pair加上双指针乱搞即可。x>0这里给一组hack23770037707hack掉两个同学的输入QWQ先输出第一个,......
  • 2023.9.25 近期练习
    CF1261FXor-Set我们把\(A,B\)集合分别处理,把其拥有的区间放到字典树上,就会拆成\(O(n\logV)\)个区间。考虑其两两组合,每个区间都是形如前面若干位确定,后面\(x\)位任意。两个区间组合,就是取\(x\)更大的那个后面都是任意的,前面的若干位合并起来即可。但是这样就会有\(......
  • 杂题总结 Vol.4
    杂题总结Vol.4试题总结2Status:OPEN\(\def\EZ{\textcolor{#51af44}{\text{EZ}}}\EZ\)表示简单,10分钟内就能想到。\(\def\HD{\textcolor{#3173b3}{\text{HD}}}\HD\)表示中等,能独立想出\(\def\IN{\textcolor{#be2d23}{\text{IN}}}\IN\)表示困难,独立思考能想到\(50\%\)......
  • 吴恩达-深度学习-课后作业-答案与总结
    deeplearning-assignment吴恩达-深度学习-课后作业-答案与总结作业只上传了ipynb文件,ipynb文件会持续更新,其它附件如预训练模型等由于太多太大,存放于网盘中执行ipynb文件所需附件下载地址,链接:百度网盘-链接不存在 密码:66gd吴恩达深度学习视频地址:进入 http://study.163......
  • AC学术中心征稿:近期将召开多场EI国际学术会议
    近期,一系列备受瞩目的国际学术会议即将召开,这些盛会不仅汇聚了来自世界各地的顶尖学者与科研人员,更涵盖了计算、通信、感知、量子技术、大数据、人工智能、物联网、网络安全等多个前沿领域。以下是对近期即将举行的部分重要国际会议的详细概览,旨在为读者提供一次跨越时空的学术......