加载中…

返回上一页

7月22日2022多校冲刺NOIP联训测试4

A.甲国的军队

题面(需要密码)

非常水的一道题,只需要把询问按照差值sort一遍,运用贪心思想累加答案即可.

#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 5000001
#define rll rg ll
using namespace std;
struct node
{
	ll a,b,c;
	inline friend bool operator<(node a,node b)
	{
		if(a.c==b.c) return a.b>b.b;
		return a.c>b.c;
	}
}a[maxn];
ll t,n,now;
ll sum[maxn],ans;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(rll i=1;i<=n;i++) cin>>a[i].a>>a[i].b,a[i].c=a[i].b-a[i].a;
		sort(a+1,a+n+1);
		ans=a[1].b;now=a[1].b-a[1].a;
		for(rll i=2;i<=n;i++)
		{
			if(now<a[i].b) ans+=a[i].b-now,now=a[i].b-a[i].a;
			else now-=a[i].a;
		}
		cout<<ans<<endl;
	}
	return 0;
}

B.虚弱

题面(需要密码)

累一个前缀,维护一个凸包,再维护两个单调栈找到正与反的最小斜率.

#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 200001
#define rll rg ll
using namespace std;
ll n,cnt;
double a[maxn],sum,qz[maxn],mx,mn,mxa,mna;
double l,r,mid,z,y;
inline double slope(ll x,ll y)
{
	return (qz[x]-qz[y])/(double)(x-y);
}
ll s1[maxn],top1,s2[maxn],top2;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	mx=1e10;
	cin>>n;
	if(n==1)
	{
		cout<<"0.000000";
		return 0;
	}
	for(rll i=1;i<=n;i++)
		cin>>a[i],qz[i]=qz[i-1]+a[i];
	for(rll i=0;i<=n;i++)
	{
		while(top1>=2&&slope(s1[top1-1],s1[top1])>=slope(s1[top1-1],i)) top1--;
		s1[++top1]=i;
	}
	for(rll i=n;i+1;i--)
	{
		while(top2>=2&&slope(s2[top2-1],s2[top2])>=slope(s2[top2-1],i)) top2--;
		s2[++top2]=i;
	}
	rll x=1,y=1;
	rg double t;
	while(x<top1||y<top2)
	{
		if(x!=top1&&(y==top2||slope(s1[x],s1[x+1])<slope(s2[y],s2[y+1])))
			t=slope(s1[x],s1[x+1]),x++;
		else t=slope(s2[y],s2[y+1]),y++;
		mx=min(mx,abs(qz[s1[x]]-(double)s1[x]*t-(qz[s2[y]]-(double)s2[y]*t)));
	}
	cout<<fixed<<setprecision(6)<<mx;
	return 0;
}

C.萨鲁曼的半兽人

题面(需要密码)

具体实现方法:
使用Manacher(一种快速匹配回文串的算法)暴力找到所有回文串,然后运用贪心思想每次找最大的子串统计即可.

#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 5000001
#define rll rg ll
using namespace std;
struct node
{
	ll l,r;
	inline friend bool operator<(node a,node b)
	{
		if(a.l==b.l) return a.r<b.r;
		return a.l<b.l;
	}
}a[maxn];
char s[maxn],tmp[maxn];
ll n,len;
ll ans;
inline void ins()
{
	len=-1;
	tmp[++len]='/';
	for(rll i=1;i<=n;i++)
	{
		tmp[++len]='#';
		tmp[++len]=s[i];
	}
	tmp[++len]='#';
	tmp[++len]='\';
	n=len-1;
}
ll pal[maxn];
inline void manacher()
{
	rll mx=0,id;
	for(rll i=1;i<=n;i++)
	{
		if(mx>=i) pal[i]=min(mx-i+1,pal[(id<<1)-i]);
		else pal[i]=1;
		while(tmp[i-pal[i]]==tmp[i+pal[i]]) pal[i]++;
		if(i+pal[i]-1>mx) mx=i+pal[i]-1,id=i;
	}
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	while(cin>>s+1)
	{
		n=strlen(s+1);ans=0;
		ins();
		manacher();
		for(rll i=1;i<=n;i++) a[i].l=i-pal[i]+1,a[i].r=i+pal[i]-1;
		sort(a+1,a+n+1);
		rll now=1,far=1;
		while(a[now].l<=1)
		{
			if(a[now].r>a[far].r) far=now;
			now++;
		}
		while(now<=n)
		{
			ans++;
			rll tmp=far;
			while(a[now].l<=a[far].r)
			{
				if(a[now].r>a[tmp].r) tmp=now;
				now++;
			}
			far=tmp;
		}
		cout<<ans-1<<endl;
	}
	return 0;
}

D.序列

题面(需要密码)

维护正序列和反序列两个ST表,来维护前缀的最小值.

#include<bits/stdc++.h>
#define ll long long
#define rg register
#define maxn 500001
#define rll rg ll
using namespace std;
struct node
{
	ll l,r,id;
	inline friend bool operator<(node a,node b)
	{
		return a.l>b.l;
	}
}a[maxn];
ll n,num,tot;
ll p[maxn],f[maxn];
ll mn1[maxn][20],mn2[maxn][20];
ll st[maxn],ed[maxn];
ll tmp1[maxn],tmp2[maxn];
vector<ll> g[maxn];
priority_queue<node> q;
inline ll getmn1(ll l,ll r)
{
	if(l==r) return l;
	rll t=log2(r-l+1);
	if(p[mn1[l][t]]<p[mn1[r-(1<<t)+1][t]]) return mn1[l][t];
	else return mn1[r-(1<<t)+1][t];
}
inline ll getmn2(ll l,ll r)
{
	if(l==r) return l;
	rll t=log2(r-l+1);
	if(p[mn2[l][t]]<p[mn2[r-(1<<t)+1][t]]) return mn2[l][t];
	else return mn2[r-(1<<t)+1][t];
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(rll i=1;i<=n;i++)
	{
		cin>>p[i];
		if(i&1) mn1[i][0]=i,mn2[i][0]=n+1;
		else mn1[i][0]=n+1,mn2[i][0]=i;
	}
	p[n+1]=0x7fffffff;
	for(rll j=1;j<=19;j++)
		for(rll i=1;i+(1<<j)<=n+1;i++)
		{
			if(p[mn1[i][j-1]]<p[mn1[i+(1<<(j-1))][j-1]]) mn1[i][j]=mn1[i][j-1];
			else mn1[i][j]=mn1[i+(1<<(j-1))][j-1];
			if(p[mn2[i][j-1]]<p[mn2[i+(1<<(j-1))][j-1]]) mn2[i][j]=mn2[i][j-1];
			else mn2[i][j]=mn2[i+(1<<(j-1))][j-1];
		}
	st[1]=1;ed[1]=n;num=1;
	while(tot<num)
	{
		if(!f[++tot]) f[tot]=f[tot-1];
		g[f[tot]].push_back(tot);
		rll l=st[tot],r=ed[tot];
		if(l&1) tmp1[tot]=getmn1(l,r);
		else tmp1[tot]=getmn2(l,r);
		if(l&1) tmp2[tot]=getmn2(tmp1[tot]+1,r);
		else tmp2[tot]=getmn1(tmp1[tot]+1,r);
		a[tot].id=tot;a[tot].l=p[tmp1[tot]];a[tot].r=p[tmp2[tot]];
		rll t=num;
		if(tmp1[tot]!=l) st[++num]=l,ed[num]=tmp1[tot]-1;
		if(tmp2[tot]!=tmp1[tot]+1) st[++num]=tmp1[tot]+1,ed[num]=tmp2[tot]-1;
		if(tmp2[tot]!=r) st[++num]=tmp2[tot]+1,ed[num]=r;
		if(t!=num) f[t+1]=tot;
	}
	q.push(a[1]);
	while(!q.empty())
	{
		rll t=q.top().id;q.pop();
		cout<<a[t].l<<' '<<a[t].r<<' ';
		for(rll i=0;i<g[t].size();i++) q.push(a[g[t][i]]);
	}
	return 0;
}
posted @ 2022-07-27 15:32  1Liu  阅读(77)  评论(0)    收藏  举报