NOIP2024 前集訓:多校A層衝刺NOIP2024模擬賽25

卡布叻_周深發表於2024-11-24

前言

music
《浮游》

天已經微亮 我睜開雙眼

長夜漫漫總有散 來到故事終點

如果有人問 此生不悔

碰觸著你的地方 刻下糾纏印痕

說再見不是離別 何必追趕著句點

思念在一瞬間

傾倒地平線

荒野在歌唱

大地在緘默

光粒穿透海

塵埃中花開

遊蜉望著天

誓言追光影

靈魂在尋找 時間縫隙

和你的方向

尋尋覓覓也不曾懷疑

思念描繪你輪廓

命運是否能重疊

說永遠太過遙遠

讓瞬間凍結時間

浮游在天地間

擁抱著原點

荒野在歌唱

大地在緘默

光粒穿透海

塵埃中花開

遊蜉望著天

誓言追光影

靈魂在尋找 時間縫隙

和你的方向

傳奇太遙遠

良夜已來臨

我們的歌謠

迴響在遠方

四季的輪換

渺小也偉大

最後的箴言 流唱世間

是心永不滅

我惱了連著打了多少天模擬賽了,根本改不完,已經忘了這場是哪天打的了。

T1 直接 bitset 操過去了,T2 想 DP,發現複雜度是假的還需要高精度,給我糖丸了的那兒打高精度,打著打著開始想罵出題人然後反應過來是不是根本不用高精度直接貪心就行了,原來小丑是我自己,直接全變成乘法就行了,然後沒有打完,賽後看題解和我的做法一模一樣,惱了。

T2 最後寫不完了擺了,直接把做法寫在註釋裡了,就當我過了……

T2 有不少細節,出題人精心挖的坑全讓造資料的填了,先是炸 long long,不過開 __int128 就行了,再是 \(x\equiv 0\) 的需要特判,然後加了兩組 hack,然後賽時就只剩一個最劣解過了……

T1 圖

直接 bitset 就行了。

點選檢視程式碼
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=1e4+10;
template<typename Tp> inline void read(Tp&x)
{
	x=0;register bool z=true;
	register char c=getchar_unlocked();
	for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
	for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
	x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,ans; char s[N]; bitset<N>vis,e[N];
signed main()
{
	freopen("a.in","r",stdin),freopen("a.out","w",stdout);
	read(n,m);
	for(int i=1;i<=m;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=n;j++) vis[j]=(s[j]=='1'||s[j]=='3');
		for(int j=1;j<=n;j++) if(s[j]=='2'||s[j]=='3') e[j]^=vis;
		for(int j=1;j<=n;j++) vis[j]=(s[j]=='2'||s[j]=='3');
		for(int j=1;j<=n;j++) if(s[j]=='1'||s[j]=='3') e[j]^=vis;
		for(int j=1;j<=n;j++) vis[j]=(s[j]=='3');
		for(int j=1;j<=n;j++) if(s[j]=='3') e[j]^=vis;
		for(int j=1;j<=n;j++) e[j][j]=0;
	}
	for(int i=1;i<=n;i++) ans+=e[i].count(); write(ans>>1);
}

T2 序列

對於每個點 操作 \(1\) 只會進行一次,操作 \(2\) 一定先進行貢獻大的。

所以可以將操作 \(1\) 看做操作 \(2\),貢獻為 \(y-x\),之後按大小排序,第 \(i\) 個操作的貢獻就可以轉化為 \(\times \dfrac{x+\sum\limits_{j=1}^{i}y_j}{x+\sum\limits_{j=1}^{i-1}y_j}\)

由此全部轉化為了乘法,排一遍序往裡加即可。

一些細節:

  • 貢獻 \(<1\) 的不要進行,因為是不超過 \(k\) 不是恰好為 \(k\)
  • 排序用分數有炸 long long 的風險,用 double 有炸精度的風險,分別注意。
  • 對於 \(x\equiv 0\) 的情況,若 \(\dfrac{x}{y}\) 滿足 \(y=0\),說明其前一定有 \(\dfrac{x'}{y'}\) 滿足 \(x'=0\),記錄一下 \(\equiv 0\) 的個數即可。
點選檢視程式碼
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=1e5+10,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
	x=0;register bool z=true;
	register char c=getchar_unlocked();
	for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
	for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
	x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,tot,b[N]; ll a[N],ans=1; vector<int>e[N]; struct aa {ll x,y;}q[N];
inline ll qpow(ll a,int b)
{ll res=1; for(a%=P;b;(a*=a)%=P,b>>=1) (b&1)&&((res*=a)%=P); return res;}
signed main()
{
	freopen("b.in","r",stdin),freopen("b.out","w",stdout);
	read(n,m); for(int i=1;i<=n;i++) read(a[i]),(ans*=(b[i]=a[i]))%=P;
	for(int i=1,op,x,y;i<=m;i++)
	{
		read(op,x,y); if(op==1) b[x]=max(b[x],y);
		else if(op==2) e[x].push_back(y); else q[++tot]={1,y};
	}
	for(int i=1;i<=n;i++)
	{
		if(b[i]!=a[i]) e[i].push_back(b[i]-a[i]);
		sort(e[i].begin(),e[i].end(),greater<int>());
		for(int j:e[i]) q[++tot]={a[i],a[i]+j},a[i]+=j;
	}
	sort(q+1,q+1+tot,[](aa a,aa b){return (__int128)a.y*b.x>(__int128)b.y*a.x;});
	for(int i=0,j=1,x,y,cnt=0;i<=m;i++,j++)
	{
		write((!cnt)*ans),putchar_unlocked(' '); if(j<=tot)
		{
			if(!(q[j].y%P)) q[j].y/=P,cnt++;
			if(!(q[j].x%P)) q[j].x/=P,cnt--;
			(ans*=q[j].y*qpow(q[j].x,P-2)%P)%=P;
		}
	}
}

T3 樹

不會。

T4 字串

難點在於詢問,發現是 \(\{(i,i+1)\mid rk_i>rk_{i+1}\}\) 的元素數量,\(rk\) 是按 \(t\) 的順序排的,於是可以用線段樹維護。

點選檢視程式碼
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
#define mid (l+r>>1)
#define ls (mid<<1)
#define rs (mid<<1|1)
#define calc(x) (((x)>=k?(x)-k:(x)))
using namespace std;
const int N=2e5+10,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
	x=0;register bool z=true;
	register char c=getchar_unlocked();
	for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
	for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
	x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,k,id[N]; char s[N];
struct aa
{
	int pre,suf,add,sum[10][10]; aa(){add=0;}
	inline aa operator + (const aa &a) const
	{
		aa tmp; for(int i=0;i<k;i++) for(int j=0;j<k;j++)
			tmp.sum[i][j]=sum[i][j]+a.sum[i][j];
		return tmp.sum[suf][a.pre]++,tmp.pre=pre,tmp.suf=a.suf,tmp;
	}
	inline aa operator + (const int &d) const
	{
		aa tmp; tmp.pre=calc(pre+d),tmp.suf=calc(suf+d);
		for(int i=0;i<k;i++) for(int j=0;j<k;j++)
			tmp.sum[calc(i+d)][calc(j+d)]=sum[i][j];
		return tmp.add=calc(add+d),tmp;
	}
}t[N<<1];
inline void build(int p,int l,int r)
{
	if(l==r) return t[p].pre=t[p].suf=s[l]-'a',void();
	build(ls,l,mid),build(rs,mid+1,r),t[p]=t[ls]+t[rs];
}
inline void change(int p,int l,int r,int vl,int vr,int d)
{
	if(vl<=l&&vr>=r) return t[p]=t[p]+d,void();
	if(t[p].add) t[ls]=t[ls]+t[p].add,t[rs]=t[rs]+t[p].add,t[p].add=0;
	if(vl<=mid) change(ls,l,mid,vl,vr,d);
	if(vr>mid) change(rs,mid+1,r,vl,vr,d); t[p]=t[ls]+t[rs];
}
inline aa ask(int p,int l,int r,int vl,int vr)
{
	if(vl<=l&&vr>=r) return t[p];
	if(t[p].add) t[ls]=t[ls]+t[p].add,t[rs]=t[rs]+t[p].add,t[p].add=0;
	if(vr<=mid) return ask(ls,l,mid,vl,vr);
	if(vl>mid) return ask(rs,mid+1,r,vl,vr);
	return ask(ls,l,mid,vl,vr)+ask(rs,mid+1,r,vl,vr);
}
inline int ask(int l,int r,int res=1)
{
	aa tmp=ask(1,1,n,l,r); for(int i=1;i<=k;i++) id[s[i]-'a']=i;
	for(int i=0;i<k;i++) for(int j=0;j<k;j++)
		res+=(id[i]>=id[j])*tmp.sum[i][j]; return res;
}
signed main()
{
	freopen("d.in","r",stdin),freopen("d.out","w",stdout);
	read(n,m,k),scanf("%s",s+1),build(1,1,n);
	for(int op,l,r,x;m;m--)
	{
		read(op,l,r); if(op==1) read(x),change(1,1,n,l,r,x);
		else scanf("%s",s+1),write(ask(l,r)),puts("");
	}
}

相關文章