1. 程式人生 > 實用技巧 >「聯賽模擬測試30 」題解

「聯賽模擬測試30 」題解

T1.maze

沙雕題,不會建議重學最短路

提示:由於是稠密資料加強會卡掉afps

T2.bird

考試時受到貪婪大陸(查詢一段區間內不同區間的個數)的影響,使勁用起點終點去推,用線段樹維護,最後也沒能搞出來

考慮暴力,先運用初中物理知識把鳥動化成人在座標軸上走

定義狀態 \(f_i\) 表示當前位置在 \(i\) ,且在 \(i\) 開槍的最大收穫

轉移: \(f_i=max(f_j+b_i-c_{i,j})\) \(b_i\) 表示 \(i\) 上空的鳥的個數, \(c_{i,j}\) 表示 \(i,j\) 共有的線段個數

炡解是線段樹,動態維護最大值和共有鳥數,區間修改,區間查最大, \(O(nlogn)\)



/* cinput
4 5
-1 1
2 4
5 9
6 8
*/
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=8e5+5,maxe=1e6+5,INF=0x3f3f3f3f;
inline int read(){
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
	return s*w;
}
int n,m,maxr,ans,f[maxn],b[maxn];
struct Node{
	int l,r;
}a[maxn];
bool cmp1(Node A,Node B){return A.l==B.l?A.r<B.r:A.l<B.l;}
struct Segment_Tree{
	int l,r,w,lazy;
}tree[maxn*4];
vector<int> g1[maxn],g2[maxn];
#define mid ((l+r)>>1)
void pushup(int rt){tree[rt].w=max(tree[rt*2].w,tree[rt*2+1].w);}
void Build(int rt,int l,int r){
	tree[rt].l=l,tree[rt].r=r;
	if(l==r)return;
	Build(rt*2,l,mid);Build(rt*2+1,mid+1,r);
}
void update(int rt,int w){
	tree[rt].w+=w,tree[rt].lazy+=w;
}
void pushdown(int rt){
	if(!tree[rt].lazy)return;
	update(rt*2,tree[rt].lazy);update(rt*2+1,tree[rt].lazy);
	tree[rt].lazy=0;
}
void modify(int rt,int s,int t,int w){
	int l=tree[rt].l,r=tree[rt].r;
	if(s<=l&&r<=t)return update(rt,w),void();
	pushdown(rt);
	if(s<=mid)modify(rt*2,s,t,w);
	if(mid<t)modify(rt*2+1,s,t,w);
	pushup(rt);
}
int query(int rt,int s,int t){
	int l=tree[rt].l,r=tree[rt].r,sum=0;
	//if(t>s)return 0;
	if(s<=l&&r<=t)return tree[rt].w;
	pushdown(rt);
	if(s<=mid)sum=query(rt*2,s,t);
	if(mid<t)sum=max(sum,query(rt*2+1,s,t));
	return sum;
}
int main(){
	freopen("bird.in","r",stdin);
	freopen("bird.out","w",stdout);
	n=read(),m=read();
	for(register int i=1;i<=n;i++){
		a[i].l=max(read()+1,1),a[i].r=read()+1;
		if(a[i].r<1)continue;
		b[a[i].l]++;b[a[i].r+1]--;
		g1[a[i].l].push_back(a[i].r);
		g2[a[i].r].push_back(a[i].l);
		maxr=max(maxr,a[i].r);
	}
	for(register int i=1;i<=maxr;i++)b[i]+=b[i-1];
	Build(1,1,maxr);
	for(register int i=1;i<=maxr;i++){
		for(register int j=0;j<g1[i].size();j++)modify(1,i,g1[i][j],-1);
		int x=b[i];
		if(i-m>=1)x+=query(1,1,i-m);
		//cout<<i<<" "<<x<<" "<<i-m<<" "<<b[i]<<" "<<query(1,1,i-m)<<" "<<g1[i].size()<<" "<<g2[i].size()<<endl;
		ans=max(ans,x);
		modify(1,i,i,x);
		for(register int j=0;j<g2[i].size();j++)modify(1,g2[i][j],i,1);
	}
	printf("%d\n",ans);
	return 0;
}

T3.stone

貌似是神仙DP,沒改

T4.椎

線段樹維護單調棧,咕了

RUA~