GDKOI 2021 Day1 PJ 爆炸记

早上睡到 7:10 分才想起今天有 GDKOI ,赶紧去买了一个面包赶去机房
发现隔壁的大奆都过来了。比赛时由于昨晚一直没睡好,打了两个小时的哈欠

T1 :暴力模拟

根据 \(r\)\(c\) 的错误个数有九种情况,

=0=1>1
=0
=1
>1

分类讨论即可

T2 :RMQ 瞎弄

对与一个询问,在左右分别找到一个最近的比他高的点
可以用 RMQ + 二分,也可以离线
本蒟蒻用了前者,复杂度\(O(n\log n+q\log n)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200005;
int x[N],n,T,p[35]={1},lg[N],f[N][35],vl;
LL sm[N],res;
inline int RMQ(int l,int r) {
	register int k=lg[r-l+1];
	return max(f[l][k],f[r-p[k]+1][k]);
}
int Left(int l,int r) {
	register int mid;
	while(l<r) {
		mid=l+r>>1;
		if(RMQ(mid+1,r)>=vl)l=mid+1;
		else r=mid;
	} return l;
}
int Right(int l,int r) {
	register int mid;
	while(l<r) {
		mid=l+r>>1;
		if(RMQ(l,mid)>=vl)r=mid;
		else l=mid+1;
	} return l;
}
int main() {
	for(int i=1;i<31;i++)p[i]=p[i-1]<<1;
	scanf("%d%d",&n,&T);
	for(int i=1;i<=n;i++)scanf("%d",&x[i]),sm[i]=1LL*x[i]+sm[i-1],f[i][0]=x[i];
	for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
	++n,x[0]=x[n]=f[n][0]=f[0][0]=2000000000;
	for(int j=1;j<31;j++)
		for(int i=0;i+p[j-1]-1<=n;i++)
			f[i][j]=max(f[i][j-1],f[i+p[j-1]][j-1]);
	for(int p,u,v;T--;) {
		scanf("%d%d",&p,&vl);
		u=Left(0,p-1),v=Right(p+1,n+1);
		res=1LL*(v-u-1)*vl-sm[v-1]+sm[u];
		printf("%lld\n",res);
	}
}

T3 贪心

真的比第一题还人口普查,直接排序贪心,用两个指针

  1. a[i]+a[j]>r ,直接删 j
  2. a[i]+a[j]<l ,直接删 i
  3. 匹配成功

T4 离线

贪心思想:钱都去买通票最后花费不会变多
离线,先将边按边权递增排序,再将查询按上限排序
把边权小于上限的边都删掉,并把删掉的边两点所在联通块合并
最后答案就是起点所在联通块点个数

#include<bits/stdc++.h>
using namespace std;
const int N=400005;
int n,m,T,ans[N],fa[N],sm[N],x[N],y[N],z[N],u[N],v[N],w[N];
void Sort(int l,int r) {
	int i=l,j=r,mid=w[l+r>>1];
	while(i<=j) {
		while(w[i]<mid)++i;
		while(w[j]>mid)--j;
		if(i<=j) {
			swap(u[i],u[j]);
			swap(v[i],v[j]);
			swap(w[i],w[j]);
			i++,j--;
		}
	}
	if(i<r)Sort(i,r);
	if(j>l)Sort(l,j);
}
inline int Fnd(int x) {
	return fa[x]^x?fa[x]=Fnd(fa[x]):x;
}
void Kp(int l,int r) {
	int i=l,j=r,mid=y[l+r>>1];
	while(i<=j) {
		while(y[i]<mid)++i;
		while(y[j]>mid)--j;
		if(i<=j) {
			swap(x[i],x[j]);
			swap(y[i],y[j]);
			swap(z[i],z[j]);
			i++,j--;
		}
	}
	if(i<r)Kp(i,r);
	if(j>l)Kp(l,j);
}
int main() {
	freopen("travel.in","r",stdin);
	freopen("travel.out","w",stdout); 
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d",&u[i],&v[i],&w[i]);
	for(int i=1;i<=m;i++)fa[i]=i,sm[i]=1;
	if(m>1)Sort(1,m);
	scanf("%d",&T);
	for(int i=1;i<=T;i++)scanf("%d%d",&x[i],&y[i]),z[i]=i;
	if(T>1)Kp(1,T);
	for(int i=1,j=1,p,q;i<=T;i++) {
		while(j<=m && w[j]<=y[i]) {
			p=Fnd(u[j]),q=Fnd(v[j]),++j;
			if(p^q)fa[q]=p,sm[p]+=sm[q];
		} ans[z[i]]=sm[Fnd(x[i])];
	}
	for(int i=1;i<=T;i++)printf("%d\n",ans[i]);
}

End

今天的第一题情况没考虑全,要细心
T2 和 T3 发挥不错, T4 这种动态题可以想想离线

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值