平邑一中NOIP提高集训Day 1

鸡立鹤群(致敬ytez传奇独苗syf

齐心协力这一块

Day1 模拟赛

平邑一中题质量确实不错

时间:2025/8/4 8:00 至 12:00 共4小时

难度:共5题 大概是 黄 黄/绿 绿 蓝/紫 蓝

由于手感过于差绝对不是笔者实力过于低下呜呜呜只打了18分呜呜呜呜

考场上。。。

先开T1

竟然是子段和!

我竟然不会子段和!

太不牛了!

开T2,暴力拿下20分

T3是好题!被硬控了!我好享受qwq

T3写了395行!我超神了!

没时间了!

T4/T5只能骗分了!

回去看T1,似乎线段树!

写!

草!没写完!

只能写暴力了!

结束了!

要挂分了!

中午在酒店。。

syf:快来快来线上分榜出了!
szh/zhc/zzl:看看我的!看看我的!
syf:额。。我草!我是rk2!!
szh/zhc/zzl:这么牛逼!!!
syf:看看你们的。。额。。zzl你20。。。
zzl:暴毙
syf:zhc你好像挂蛋了。。
zhc:暴毙
syf:szh你37分。。
szh:暴毙

szh线上榜分:0 20 17 0 0

回机房了!

得到了我的线下榜分(最终分)

szh线下榜分:0 0(谁给我T2卡掉了!) 18 0 0

总分:18分

大唐盛世

喜报:wsw把std的T3正解hack掉了!!

发挥太逊了必须改正

笔者赛后std

T1

原题传送门

Solution

竟然不是线段树。。

第一眼:我们需要一种支持修改和查询的数据结构。

考虑两种操作:

1.修改:希望删除后不选,由于值域非负,可以将删除改为单点修 -INF。

2.查询:最大子段和,不难想到用线段树维护:维护区间最大子段和、区间和、区间最大前缀和以及区间最大后缀和。

但是这是T1捏,线段树还是太麻烦了

第二眼:n 个元素一个个删除,且只有这一种修改,且不强制在线。

套路:时间回溯,正难则反。

将删除反过来看作添加,直接并查集维护就好了。

维护答案时,由于a中元素非负,只需要直接更新 max。

Code

#include <bits/stdc++.h>
#define int long long
#define PII pair<int,int>
#define fi first
#define se second
using namespace std;
int read(){
    int s=0,f=1;
    char p=getchar();
    while(p<'0'||p>'9'){
        if(p=='-') f=-1;
        p=getchar();
    }
    while(p>='0'&&p<='9'){
        s*=10;
        s+=p-'0';
        p=getchar();    
    }
    return s*f;
}
const int N=5e5+5;
int fa[N],n,c[N],s[N],q[N],ans[N];
int find(int x){
    if(fa[x]==x) return x;
    return fa[x]=find(fa[x]);    
}
signed main(){
//    freopen("kill.in","r",stdin);
//    freopen("kill.out","w",stdout);
    cin>>n;
    for(int i=1;i<=n;++i){
        fa[i]=i;
        cin>>c[i];
    }
    memset(s,-1,sizeof s);
    int maxn=0; 
    for(int i=1;i<=n;++i){
        cin>>q[i];
    }
    for(int i=n;i>=2;--i){
        int x=q[i];
        s[x]=c[x];
        maxn=max(maxn,s[x]);
        if(s[find(x-1)]!=-1){
            s[find(x-1)]+=c[x];
            maxn=max(maxn,s[find(x-1)]);
            fa[x]=find(x-1);    
        }
        if(s[find(x+1)]!=-1){
            s[find(x+1)]+=s[find(x)];
            maxn=max(maxn,s[find(x+1)]);
            fa[find(x)]=find(x+1);    
        }
        ans[i]=maxn;
    }
    for(int i=2;i<=n;++i) cout<<ans[i]<<'\n';
    cout<<0<<'\n';
}

T2

Solution

注意到值域很小,我们考虑与值域有关的做法。

\(f_i\) 表示 \(a_1..._i\) 的逆序对个数。

询问时我们只需要先计算 \(f_r-f_l−1\)然后消除 \([1,l)\) 与$ [l,r]$ 之间的贡献即可。

只需要对于每个$x $求出 \([l,r]\)中 $ x $的个数以及 \([1,l)\) 中$ >x $的个数。

这可以通过预处理二维前缀和得到。时间复杂度$ O((n + m)V)\(,其中\) V$ 为值域。

Code

#include <bits/stdc++.h>
#define PII pair<int,int>
#define fi first
#define se second
using namespace std;
int read(){
    int s=0,f=1;
    char p=getchar();
    while(p<'0'||p>'9'){
        if(p=='-') f=-1;
        p=getchar();
    }
    while(p>='0'&&p<='9'){
        s*=10;
        s+=p-'0';
        p=getchar();
    }
    return s*f;
}
int n,q;
const int N=1e6+5,M=55;
int c[N],a[N][M];
long long s[N],qzh[N],tmp[N],hzh[N];
int main(){
//    freopen("interval.in","r",stdin);
//    freopen("interval.out","w",stdout);
    cin>>n>>q;
    for(int i=1;i<=n;++i){
        c[i]=read();
        for(int j=1;j<=50;++j){
            a[i][j]=a[i-1][j];    
        }
        a[i][c[i]]++;
        for(int j=c[i]+1;j<=50;++j){
            s[i]+=a[i-1][j];
        }
        qzh[i]=qzh[i-1]+s[i];
    }
    while(q--){
        int l,r;
        l=read(),r=read();
        for(int i=50;i>=1;--i){
            tmp[i]=a[r][i]-a[l-1][i];
            hzh[i]=hzh[i+1]+a[l-1][i];
        }
        long long ans=qzh[r]-qzh[l-1];
        for(int i=1;i<=50;++i){
            ans-=hzh[i+1]*tmp[i];
        }
        cout<<ans<<'\n';
    }
    return 0;
}

T3

原题传送门

Solution

另外,这道题我的考场思路竟跟std出奇的一致!!

但是我只拿了18分呜呜呜

部分分还是比较足的。

考虑一下正解,手玩几组数据不难发现想到贪心,可以分类讨论一下

1.形如 101,发现如果将中间的 0 填充,有 3 个贡献。

2.形如 10 或 01,发现将的 0 填充,有 2 个贡献。

3.形如 0,将其填充获得 1 个贡献。

注意不要重复,打个标记即可。

极端情况:全0。。。

Code(18分板,这题真的很有意思,快来补题

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 7;

int read()
{
	int x = 0, w = 1;
	char ch = getchar();
	while(ch > '9' || ch < '0')
	{
		if(ch == '-')
		{
			w = -1;
		}
		ch = getchar();
	}
	while(ch <= '9' && ch >= '0')
	{
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * w;
}

long long Qmi(int a, int b, int p)
{
	if(b == 0)
	{
		return 1%p;
	}

	if(b == 1)
	{
		return a%p;
	}

	long long ans = Qmi(a, b/2, p);

	ans = ans*ans%p;

	if(b % 2)
	{
		ans = ans*a%p;
	}

	return ans % p;
}

bool isprime(long long x)
{
	if(x <= 1)
	{
		return false;
	}
	if(x == 2)
	{
		return true;
	}
	if(x % 2 == 0)
	{
		return false;
	}
	for(int i = 3;  i <= sqrt(x);  i += 2)
	{
		if(x % i == 0)
		{
			return false;
		}
	}
	return true;
}

int n, q;

string s;

int cnt;

int dn[MAXN], t[MAXN], qzh[MAXN], hzh[MAXN];

int lenn;

bool f;

int ansft;

int main()
{
	freopen("string.in", "r", stdin);
	freopen("string.out", "w", stdout);

	cin>>n>>q;

	cin>>s;

	if(s[0] == '1')
	{
		f = 1;
	}

	for(int i = 0;  i < n;  i++)
	{
		if(s[i] == '1')
		{
			cnt++;
			if(s[i-1] == '1')
			{
				if(s[i-2] != '1')
				{
					ansft += 2;
				}
				else
				{
					ansft += 1;
				}
			}
		}

		if(s[i] != s[i-1])
		{
			lenn++;
		}

		dn[lenn]++;
	}

//	for(int i = 1;  i <= lenn;  i++)
//	{
//		qzh[i] = qzh[i-1] + dn[i];
//	}
//
//	for(int i = lenn;  i >= 1;  i--)
//	{
//		hzh[i] = hzh[i+1] + dn[i];
//	}

	while(q--)
	{
		int x;

		bool flag = 0;

		for(int i = 1;  i <= lenn;  i++)
		{
			t[i] = dn[i];
		}

		cin>>x;

		if(x == 0)
		{
			cout<<ansft<<endl;
			continue;
		}

		if(x + cnt <= 1)
		{
			cout<<0<<endl;
			continue;
		}

		if(x + cnt == n)
		{
			cout<<n<<endl;
			continue;
		}

		if(cnt == 0)
		{
			cout<<x<<endl;
			continue;
		}

		int cntc3 = 0, cntc2 = 0, cntc1 = 0;

		int step = 0;

		if(f)
		{
			for(int i = 2;  i <= lenn;  i+=2)
			{
				if(t[i] == 1)
				{
					if(t[i-1] == 1 && t[i+1] == 1)
					{
						cntc3++;
						t[i-1] += 2;
						t[i] += 2;
						t[i+1] += 2;
						step++;
						continue;
					}
				}
				if(step >= x)
				{
					if(step == x)
					{
						cout<<(3 * cntc3 + 2 * cntc2 + cntc1) + ansft<<endl;
						flag = 1;
						break;
					}
					else
					{
						if(cntc3 >= x)
						{
							cout<<(3 * x) + ansft<<endl;
						}
						else if(cntc3 + cntc2 >= x)
						{
							cout<<(3 * cntc3 + 2 * (x - cntc3)) + ansft<<endl;
						}
						else if(cntc3 + cntc2 + cntc1 >= x)
						{
							cout<<(3 * cntc3 + 2 * cntc2 + (x - cntc3 - cntc2 + 1)) + ansft<<endl;
						}
						flag = 1;
						break;
					}
				}
			}

			if(flag)
			{
				continue;
			}

			for(int i = 2;  i <= lenn;  i+=2)
			{
				if(t[i] == 1)
				{
					if(t[i-1] == 1 || t[i+1] == 1)
					{
						if(t[i-1] == 1)
						{
							cntc2++;
							t[i-1] += 2;
							t[i] += 2;
							step++;
							continue;
						}
						if(t[i+1] == 1)
						{
							cntc2++;
							t[i+1] += 2;
							t[i] += 2;
							step++;
							continue;
						}
					}
				}

				if(step >= x)
				{
					if(step == x)
					{
						cout<<(3 * cntc3 + 2 * cntc2 + cntc1) + ansft<<endl;
						flag = 1;
						break;
					}
					else
					{
						if(cntc3 >= x)
						{
							cout<<(3 * x) + ansft<<endl;
						}
						else if(cntc3 + cntc2 >= x)
						{
							cout<<(3 * cntc3 + 2 * (x - cntc3)) + ansft<<endl;
						}
						else if(cntc3 + cntc2 + cntc1 >= x)
						{
							cout<<(3 * cntc3 + 2 * cntc2 + (x - cntc3 - cntc2 + 1)) + ansft<<endl;
						}
						flag = 1;
						break;
					}
				}
			}

			if(!flag)
			{
				cout<<(3 * cntc3 + 2 * cntc2 + (x - cntc3 - cntc2 + 1)) + ansft<<endl;
			}
		}
		else
		{
			for(int i = 1;  i <= lenn;  i+=2)
			{
				if(t[i] == 1)
				{
					if(t[i-1] == 1 && t[i+1] == 1)
					{
						cntc3++;
						t[i-1] += 2;
						t[i] += 2;
						t[i+1] += 2;
						step++;
						continue;
					}
				}
				if(step >= x)
				{
					if(step == x)
					{
						cout<<(3 * cntc3 + 2 * cntc2 + cntc1) + ansft<<endl;
						flag = 1;
						break;
					}
					else
					{
						if(cntc3 >= x)
						{
							cout<<(3 * x) + ansft<<endl;
						}
						else if(cntc3 + cntc2 >= x)
						{
							cout<<(3 * cntc3 + 2 * (x - cntc3)) + ansft<<endl;
						}
						else if(cntc3 + cntc2 + cntc1 >= x)
						{
							cout<<(3 * cntc3 + 2 * cntc2 + (x - cntc3 - cntc2 + 1)) + ansft<<endl;
						}
						flag = 1;
						break;
					}
				}
			}

			if(flag)
			{
				continue;
			}

			for(int i = 1;  i <= lenn;  i+=2)
			{
				if(t[i] == 1)
				{
					if(t[i-1] == 1 || t[i+1] == 1)
					{
						if(t[i-1] == 1)
						{
							cntc2++;
							t[i-1] += 2;
							t[i] += 2;
							step++;
							continue;
						}
						if(t[i+1] == 1)
						{
							cntc2++;
							t[i+1] += 2;
							t[i] += 2;
							step++;
							continue;
						}
					}
				}

				if(step >= x)
				{
					if(step == x)
					{
						cout<<(3 * cntc3 + 2 * cntc2 + cntc1) + ansft<<endl;
						flag = 1;
						break;
					}
					else
					{
						if(cntc3 >= x)
						{
							cout<<(3 * x) + ansft<<endl;
						}
						else if(cntc3 + cntc2 >= x)
						{
							cout<<(3 * cntc3 + 2 * (x - cntc3)) + ansft<<endl;
						}
						else if(cntc3 + cntc2 + cntc1 >= x)
						{
							cout<<(3 * cntc3 + 2 * cntc2 + (x - cntc3 - cntc2 + 1)) + ansft<<endl;
						}
						flag = 1;
						break;
					}
				}
			}

			if(!flag)
			{
				cout<<(3 * cntc3 + 2 * cntc2 + (x - cntc3 - cntc2 + 1)) + ansft<<endl;
			}
		}
	}

	return 0;
}

因时间原因,T4T5详见std

posted @ 2025-08-05 17:36  include_qwq  阅读(34)  评论(3)    收藏  举报