NOIP模擬99 多校31

2022-09-18 07:27:25 字數 4248 閱讀 6773

原題3100,張口放 t1(出題人原話)

思維題,合法的情況其實就是上下兩個梯形拼起來的樣子。

他們的邊界都是在 \(i\) 軸上面,但是不能相交。

於是我們可以嘗試兩者相交的縱座標,再列舉左邊梯形的下邊界一級右邊梯形的上邊界,對於答案的話再乘上乙個二。

\[\displaystyle\sum_^\sum_^\sum_^\binom\times\binom\times\binom\times\binom

\]同樣的,對於上下兩個梯形的情況我們可以把兩個邊長交換一下再做一遍來實現。

但是有一種情況是重複的,也就是兩個顏色都是兩個聯通塊,也就是兩個梯形的邊界相鄰的情況,這個注意一下迴圈邊界問題就好了。

然後再觀察一遍這個柿子,它是可以字尾和優化的。。複雜度 \(\mathcal(n^2)\)

#include#define int long long

#define ull unsigned long long

#define f() cout<

while(ch>='0'&&ch<='9')

return x*f;

}const int n=4e3+100,mod=998244353;

int n,m,ans,fac[n],ifac[n],suf[n];

int power(int x,int y,int p=mod)

void init(int lim)

void add(int &x,int y)

int c(int x,int y)

while(ch>='0'&&ch<='9')

return x*f;

}const int n=2e5+10;

int n,m,tim,dfn[n],siz[n],topp[n],son[n],fa[n],dep[n],ans[n];

int tot=1,head[n],nxt[n<<1],ver[n<<1];

bool vis[n];

pairs[n],q[n];

struct nodedis[10];

void add_edge(int x,int y)

void dfs1(int x)

bool comp(node x,node y)

int dist(int x,int y)

struct dsu

int find(int x)

void merge(int x,int y)

; dis[2]=(node);

dis[3]=(node);

dis[4]=(node);

dis[5]=(node);

dis[6]=(node);

sort(dis+1,dis+7,comp); s[y]=; fa[x]=y;

}}d;

#undef int

int main()

pairtemp=s[d.find(q[i].second)]; int pos=q[i].second;

ans[i]=max(dist(pos,temp.first),dist(pos,temp.second));

} for(int i=1;i<=m;i++) if(q[i].first==2) printf("%lld\n",ans[i]);

return 0;

}

先假設我們可以求出每一行的不同性別的個數,顯然每一行可能的貢獻只和這一行的數量較小的性別有關係。

並且這個東西是和順序無關的,那麼我們從小到大排序之後的陣列假設為 \(s\) 。

那麼就乙個詢問 \((x,y)\) 而言,最優策略一定是選擇後 \(x\) 個,對於每乙個 \(s_i\) 而言,設 \(t=\min(s_i,\frac)\) ,這個位置的貢獻就是 \(t\times(y-t)\) 。

我們可以二分出乙個邊界,對於 \(s_i>\frac\) 的情況直接算就好了,另一種情況的答案就是 \((y-s_i)\times s_i\) 也就是 \(y\times s_i+s_i^2\) 維護兩個字首和就好了。

現在考慮如何求出每個性別的個數,掃瞄線是毋庸置疑的,發現 k 非常小,於是我們可以維護乙個區間內的前 \(k\) 小的值以及對應個數,直接歸併合併即可。

#include#define int long long

#define ull unsigend long long

#define f() cout<

while(ch>='0'&&ch<='9')

return x*f;

}const int n=3e5+10;

int n,m,t,mn,q,s[n],pre[n],pre2[n];

vector< pair> v[n];

pairtemp[n<<1];

struct segment_tree

while(pos<=tre[rs].size()-1) temp[++cnt]=tre[rs][pos++];

for(int i=1;i<=cnt;i++)

if(tre[x][tre[x].size()-1].first==it.first) tre[x][tre[x].size()-1].second+=it.second;

else tre[x].push_back(it);

} while(tre[x].size()>mn) tre[x].pop_back();

} void push_down(int x)

void build(int x,int l,int r)

),void();

int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); push_up(x);

} void insert(int x,int l,int r,int l,int r,int val)

int mid=(l+r)>>1; if(laz[x]) push_down(x);

if(l<=mid) insert(ls,l,mid,l,r,val);

if(r>mid) insert(rs,mid+1,r,l,r,val);

push_up(x);

}}t;

#undef int

int main()

),v[x2+1].push_back();

for(int i=1;i<=n;i++)

printf("%lld\n",(n-pos+1)*(y/2)*(y-y/2)+y*(pre[pos-1]-pre[n-x])-(pre2[pos-1]-pre2[n-x]));

} return 0;

}

用兩個棧維護佇列的情況。

發現轉移是乙個矩陣,記錄從 \(i\rightarrow j\) 的方案數

那麼我們維護兩個棧,每個維護一段區間\([head,mid],[mid+1,tail]\)。

第乙個棧的第 \(i\) 個元素,維護從第 \(i\) 行到第 \(mid\) 行的轉移

第二個棧的元素維護從 \(mid\) 到 \(j\) 的轉移。

插入操作直接在第二個棧加入乙個元素,刪除操作需要分類討論第乙個棧的情況,詢問直接將兩個棧合併即可。

由於是馬步,所以需要維護 \(i\rightarrow mid+1,mid+1\rightarrow j\) 的轉移。。

#include#define int long long

#define ull unsigned long long

#define f() cout<

while(ch>='0'&&ch<='9')

return x*f;

}const int n=1e5+10,m=25,mod=998244353;

int q,n,head=1,tail,mid,f[n][m][m],g[n][m][m];

char ch[m];

bool s[n][m];

void add(int &x,int y)

void work(int now,int pre1,int pre2,int dp[m][m])

}void rebuild()

void insert()

void solve()

printf("%lld\n",ans);

}#undef int

int main()

return 0;

}

noip多校模擬28

考試過程 這次考試,感覺不在狀態。四個題都沒有什麼正解的思路,心態也比較不好。總體來說今天的狀態不是很好,需要及時調整。因為我幾天前做了一道期望題,那個題是資料範圍也是比較小,而且正解是 o n 的,所以這道題我也就一直在想 o n 的做法,想了乙個多小時,沒什麼思路,就直接棄了。但是正解是 o n...

NOIP模擬91 多校24

簽到題 然而我陣列開小直接變成暴力分。發現其實就是第一類斯特林數,然後 n 2 推就好了。感覺可以用 ntt 優化成 nlogn 但是好像並沒有什麼卵用 再說了,我也不會。include define int long long define ull unsigned long long defin...

NOIP模擬賽多校聯考 Round7題解

對任意數求分解為2的冪之和有多少種分法。奇怪的遞推。手玩小樣例得知答案序列為n級等差數列。貌似碾標算 include using namespace std namespace standardio templateinline void write t x using namespace stan...