2019.06.06 【NOIP提高组】模拟 A 组

本文深入解析了JZOJ竞赛中的三道经典题目:求导、成绩调研与跟踪,提供了详细的算法思路与代码实现,涵盖了多项式求导、双指针优化及树形结构遍历等关键知识点。

前言

原地爆炸炸炸炸炸炸炸炸炸炸炸炸炸炸炸炸炸炸


JZOJ 4803 求导

题目

一个单项式 a x b ax^b axb求导为 ( a b ) x b − 1 (ab)x^{b-1} (ab)xb1,现把一个多项式求导


分析

其实就是道大模拟,只是太坑了,对于指数为0、1、2都要单独处理,要开long long,然后如果没有输出要输出0
代码太丑就不贴了


JZOJ 4804 成绩调研

在这里插入图片描述


分析

这道题用双指针解决,首先枚举右端点 i i i,可用的答案应该是一段连续的区间 [ h e a d ∼ t a i l − 1 ] [head\sim tail-1] [headtail1]
对于 h e a d head head只要当前右端点的位置超过 r i r_i ri,那么就让 h e a d + 1 head+1 head+1
对于 t a i l tail tail也就是让该位置到右端点正好不满足,但是很难实现
考虑记录变量 t t t表示还不满足多少的要求,当 t = 0 t=0 t=0时, t a i l tail tail就可以不断向前扩张了
时间复杂度 O ( n ) O(n) O(n)


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
int n,m,t,a[200001],l[200001],cnt1[200001],cnt2[200001],r[200001];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
signed main(){
	freopen("survey.in","r",stdin);
	freopen("survey.out","w",stdout); 
	n=iut(); t=m=iut(); long long ans=0;
	for (rr int i=1;i<=n;++i) a[i]=iut();
	for (rr int i=1;i<=m;++i) l[i]=iut(),r[i]=iut(),t-=!l[i];
	for (rr int i=1,head=1,tail=1;i<=n;++i){
		++cnt1[a[i]],++cnt2[a[i]];
		t-=cnt2[a[i]]==l[a[i]];
		while (cnt1[a[i]]>r[a[i]]) --cnt1[a[head]],++head;
		while (!t&&tail<=i){
			--cnt2[a[tail]];
			t+=cnt2[a[tail]]==l[a[tail]]-1;
			++tail;
		}
		ans+=(tail>head)*(tail-head);
	}
	printf("%lld",ans);
	return 0;
} 

JZOJ 4805 跟踪

题目

在一棵树上,有三个人,一个每次可以静止或走一步的人被两个一次走两步的人追,问最晚什么时候被追到


分析

首先预处理树上每个点最早能被那两个人追上的时间,然后判断被追的人是否在这个点可以苟延残喘,然后我就WA了,看了数据,我的答案加一就全过了,可是我这样连样例都不能过呀???于是就改了一会,虽然慢了,但是至少是正解


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
struct node{int y,next;}e[400101];
int ls[200101],dis[2][200101],n,rt,rt1,rt2,k=1,ans;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
void dfs(int x,int fa,int p){
	for (rr int i=ls[x];i;i=e[i].next)
	if (e[i].y!=fa&&dis[p][e[i].y]>dis[p][x]+1){
		dis[p][e[i].y]=dis[p][x]+1;
		dfs(e[i].y,x,p);
	}
}
void dfs1(int x,int fa){
	if ((dis[1][x]<<1)>dis[0][x]) return;
	rr int t=((dis[0][x]+1)>>1)*3-(dis[0][x]&1);
	ans=ans>t?ans:t;
	for (rr int i=ls[x];i;i=e[i].next)
	    if (e[i].y!=fa) dfs1(e[i].y,x);
}
signed main(){
	freopen("track.in","r",stdin);
	freopen("track.out","w",stdout);
	memset(dis,42,sizeof(dis));
	n=iut(); rt=iut(); rt1=iut(); rt2=iut();
	for (rr int i=1;i<n;++i){
		rr int x=iut(),y=iut();
		e[++k]=(node){y,ls[x]}; ls[x]=k;
		e[++k]=(node){x,ls[y]}; ls[y]=k;
	}
	dis[0][rt1]=0,dfs(rt1,0,0),dis[0][rt2]=0,dfs(rt2,0,0),dis[1][rt]=0,dfs(rt,0,1); dfs1(rt,0);
	return !printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值