NOIP2024 前集訓:NOIP2024加賽 5

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

前言

music
《浮光》

看指尖撥響蝴蝶 扇動一場離別

我推開無聲歲月 續夢一頁

你我只是打個照面 可曾有過誓約

走進熟悉卻 陌生的思念

啊……

啊……

你的眼眸 裝滿了時間

你的身後 擁故事成篇

此生如夢 願細數流年

與你同寫 滄海桑田

浮光掠影 重山彩雲間

你的伏線 穿越千百年

人生不過 恍惚三萬天

漫漫人間 留戀流連

你說那月光 照過同樣城牆

永恆的剎那的 此刻沉默無話

想問你這星空 是否不曾變

是啊 是啊 我們望著它

風吹過耳旁 古遠的歌唱啊

這是我也是你 不曾遺忘的啊

是來路是去處 是你在回答

去吧 去啊 總會相遇吧

你的眼眸 裝滿了時間

你的身後 擁故事成篇

此生如夢 願細數流年

與你同寫 滄海桑田

浮光掠影 重山彩雲間

你的伏線 穿越千百年

人生不過 恍惚三萬天

漫漫人間 留戀流連

先寫點閒話。

明天(發的時候已經是今天了)就要放假了開心O(∩_∩)O~~,就放一天不開心 ̄へ ̄。

還要開家長會?不知道我們這種期中沒考選科也毫無懸念的過來開家長會的意義何在……

明天還有模擬賽?到底打不打?真打的話打一半就得走。

晚上(21:10 左右)網沒了?feifei 說出故障了,過了一會兒修復了。

宿舍的遠古電話交換機太破了老是佔線煩死了。

中午讓我推歌,好耶放周深的,想要放《一期一會》,huge 說要放大家可能聽過的跟著唱,不是都沒聽過《未聞花名》嗎?改成《浮光》,還要我跟著唱,不是我耳朵有毛病不會跟著唱,深深唱得那麼好聽靜靜欣賞不好麼,要麼只聽要麼自己唱,好像機房聽過這個的也不多(就算聽過也唱不上去),一幫人默默地聽沒人唱。

好了該說比賽了,就是掛的快比得的分多了,T1 只篩到 \(m\) 被 hack 哩(全機房都被 hack 了),T2 部分分給了足足 \(80\),那我還想個屁正解直接寫部分分,沒開 long long 掛 \(30\)?!?T4 我會部分分!沒打完……

T1 題面一開始還是錯的,所以先打的 T2,T2 飛快拿到 \(80\) 後去寫 T1,發現二分顯然就開打,然後讀假題了,我甚至在那兒懷疑大樣例是錯的都沒有懷疑自己讀假題了,瞪了 \(2\) 個多小時發現讀假題了,發現加個埃篩就過了。

T2 出線段樹分治板子,記得上次出珂朵莉維護顏色段板子也是部分分給了足足 \(80\)

huge 坦白是往年學長加的 hack,還科普了為什麼飲水機會漏。

image

T1 暴力操作

顯然可以二分答案。

因為 \(\lfloor\dfrac{a}{bc}\rfloor=\lfloor\dfrac{\lfloor\frac{a}{b}\rfloor}{b}\rfloor\),對於一個 \((a_i,x)\) 所滿足 \(\lfloor\dfrac{a_i}{x}\rfloor\le mid,x<y\) 一定滿足 \(\lfloor\dfrac{a_i}{y}\rfloor\le mid\),所以先對於 \(c_i\) 做一次字尾 \(\min\),再跑一邊埃篩(類似揹包吧):\(\forall j\mid i,c_{i}=\min(c_i,c_j\times c_{\frac{i}{j}})\),之後再做一次字尾 \(\min\),使每次操作代價最小。

這裡需要注意一個細節,不能只篩到 \(m\),如 \(n=7\),則 \(7\) 可以透過 \(3\times 3\) 替換掉,但此時他是 \(9\),所以 \(9\) 也要篩到,保險起見篩到 \(2m\)

對於 check,先將 \(a\) 按升序排序,對於一個數是中位數的必要條件是 \(\sum\limits_{i=1}^n[a_i\le x]\ge \lfloor\dfrac{n}{2}\rfloor+1\),若滿足就往左二分即可,滿足該條件的最小的一個一定是中位數,對於 \(n\) 為奇數顯然正確,對於 \(n\) 為偶數,考慮中位數等於 \(\dfrac{a_{\frac{n}{2}}+a_{\frac{n}{2}+1}}{2}\),現在顯然有 \(a_{\frac{n}{2}}\le mid\),若能夠使 \(a_{\frac{n}{2}+1}< mid\) 則此時中位數是 \(<mid\) 的,答案還能再小,直到最小的一個滿足的。

具體如何找到一個 \(x\) 滿足 \(\lfloor\dfrac{a_i}{x}\rfloor\le mid\),有 \(\dfrac{a_i}{x}<mid+1\),則 \(x>\dfrac{a_i}{mid+1}\),即 \(x\ge \lfloor\dfrac{a_i}{mid+1}\rfloor+1\),也可以雙指標跑,D 一下部分人二分找 \(x\) 的雙 \(\log\) 做法。

複雜度 \((n+m)\log m\)

點選檢視程式碼
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=5e5+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,k,ans,a[N],b[N<<1];
inline bool check(int x)
{
	int pos=upper_bound(a+1,a+1+n,x)-a-1,res=0;
	if(pos>(n>>1)) return 1;
	for(int i=pos+1;i<=(n>>1)+1;i++) (res+=b[a[i]/(x+1)+1])>k&&(i=n);
	return res<=k;
}
signed main()
{
	freopen("opt.in","r",stdin),freopen("opt.out","w",stdout);
	read(n,m,k);
	for(int i=1;i<=n;i++) read(a[i]); sort(a+1,a+1+n);
	for(int i=1;i<=m;i++) read(b[i]); fill(b+m+1,b+2*m+1,1e9+1);
	for(int i=m-1;i;i--) b[i]=min(b[i],b[i+1]);
	for(int i=1;i<=2*m;i++) for(int j=2*i;j<=2*m;j+=i) b[j]=min(b[j],b[i]+b[j/i]);
	for(int i=2*m-1;i;i--) b[i]=min(b[i],b[i+1]);
	for(int l=0,r=m,mid;l<=r;) check(mid=l+r>>1)?r=(ans=mid)-1:l=mid+1;
	write(ans);
}

T2 異或連通

  • P5787 二分圖 /【模板】線段樹分治

發現每個 \(w_i\) 能夠存在對應的區間不超過 \(\log k\) 段,這個是能夠用 01trie 求出來的。

之後就是線段樹分治板子了,就是線上段樹上跑 dfs 加回溯,用可撤銷並查集維護。

點選檢視程式碼
#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)
using namespace std;
const int N=1e5+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,q,k,top,res,tot=1,u[N],v[N],w[N],a[N],b[N],f[N],fa[N],sz[N],sta[N],ans[N],l[N<<5],r[N<<5],son[N<<5][2];
vector<int>g[N],t[N<<1]; unordered_map<int,int>mp;
inline int find(int x) {while(x!=fa[x]) x=fa[x]; return x;}
inline void merge(int x,int y)
{
	sz[x]>sz[y]&&(x^=y^=x^=y),fa[sta[++top]=x]=y,res-=f[y],res-=f[x];
	res+=(f[y]+=1ll*sz[x]*sz[y]+f[x]),sz[y]+=sz[x];
}
inline void undo(int ltop,int lres)
{
	for(int x,y;top>ltop;top--,f[y]-=1ll*sz[x]*sz[y]+f[x])
		x=sta[top],y=fa[sta[top]],sz[y]-=sz[x],fa[x]=x; res=lres;
}
inline void add(int p,int l,int r,int vl,int vr,int x)
{
	if(vl==0) return ; if(vl<=l&&vr>=r) return t[p].push_back(x),void(0);
	if(vl<=mid) add(ls,l,mid,vl,vr,x); if(vr>mid) add(rs,mid+1,r,vl,vr,x);
}
inline void ask(int p,int l,int r)
{
	int ltop=top,x,y,lres=res;
	for(int i:t[p]) if((x=find(u[i]))!=(y=find(v[i]))) merge(x,y);
	if(l==r) {for(int i:g[l]) ans[i]=res; return undo(ltop,lres),void();}
	ask(ls,l,mid),ask(rs,mid+1,r),undo(ltop,lres);
}
inline void insert(int x,int id)
{
	for(int i=30,p=1,c;~i;i--,r[p=son[p][c]]=id)
		if(!son[p][c=(x>>i)&1]) l[son[p][c]=++tot]=id;
}
inline void ask(int id)
{
	for(int i=30,p=1,c,d,j;~i&&p;i--)
	{
		j=son[p][c=(w[id]>>i)&1],d=(k>>i)&1;
		if(d) add(1,1,b[0],l[j],r[j],id),p=son[p][c^1]; else p=j;
	}
}
signed main()
{
	freopen("xor.in","r",stdin),freopen("xor.out","w",stdout);
	read(n,m,q,k); for(int i=1;i<=n;i++) fa[i]=i,sz[i]=1;
	for(int i=1;i<=m;i++) read(u[i],v[i],w[i]);
	for(int i=1;i<=q;i++) read(a[i]),b[i]=a[i];
	sort(b+1,b+1+q),b[0]=unique(b+1,b+1+q)-b-1;
	for(int i=1;i<=b[0];i++) insert(b[i],mp[b[i]]=i);
	for(int i=1;i<=q;i++) g[mp[a[i]]].push_back(i);
	for(int i=1;i<=m;i++) ask(i); ask(1,1,b[0]);
	for(int i=1;i<=q;i++) write(ans[i]),puts("");
}

T3 詭異鍵盤

沒有太大改的慾望,留最後改吧。

T4 民主投票

還沒有改,有空馬上改。

相關文章