至於10.3號的模擬爲何今天寫。。。。這種事情不是很顯而易見嘛。node
我但是養鴿大戶QAQios
其實這兩天的題都還好,不算難。ide
考試考結論以及數學對我來講最不友好了啊QAQ優化
雞腿想到了一個很高(sha)明(bi)的問題,在 N 條水平線與 M 條豎直線構成的網格中,放 K 枚石子,每一個石子都只能放在網格的交叉點上。問在最優的擺放方式下,最多能找到多少四邊平行於座標軸的長方形,它的四個角上都剛好放着一枚石子。spa
對於大家來講,這種結論題簡直顯然。code
可是我打完T2,T3以後一個多小時全在搞這個題,最後交了個暴力QAQblog
能把點堆在一塊兒就堆在一塊兒。多出來的位置再單獨計算。數學
那麼這題咱們只須要枚舉能圍城的邊長,而後處理多出來的部分,就完事了。string
代碼it
數學菜雞跟着題解改了小一個小時QAQ
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n,m,k,ans=0; int ad(int x,int y,int i) { return x*(x-1)/2*i*(i-1)/2+y*(y-1)/2*x; } int main() { scanf("%d%d%d",&n,&m,&k); for(int i=2;i<=m;i++) { int x=k/i,y=k%i; if(x>n) continue; if(x==n&&y) continue; ans=max(ans,ad(x,y,i)); } for(int i=2;i<=n;i++) { int x=k/i,y=k%i; if(x>m) continue; if(x==m&&y) continue; ans=max(ans,ad(x,y,i)); } cout<<ans<<endl;; return 0; }
這題簡直友好啊友好。
Alice爲了刁難你,拆掉編號從l到r的邊,固然你須要作的事情就是求連通塊的個數。
不記得在哪次集訓的時候講過的一種思想了,還好還記得。
運用相似分塊的思想【多是我太喜歡分塊了QAQ
把圖中的點看做3部分:
1. l前
2. r後
3. l~r
那麼若是要是想要求出 除了l~r 的信息,那不就是隻求第一和第三部分的結果嗎?
很顯然,咱們能夠很輕鬆的經過預處理的方法求出任意位置x的1~x和x~n的結果。
詢問的答案就是使用預處理的答案,fa[l-1]與fa[r+1]的值進行合併。
那麼顯然這就是一個二維並查集維護連通塊個數的問題了。
代碼來啦
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n,m,k; struct ss{ int l,r; }d[100007]; int a[510],fa[10007][510],ba[10007][510]; int fi_fa(int id,int x) { if(fa[id][x]==x) return x; return fa[id][x]=fi_fa(id,fa[id][x]); } int fi_ba(int id,int x) { if(ba[id][x]==x) return x; return ba[id][x]=fi_ba(id,ba[id][x]); } int fi_a(int x) { if(a[x]==x) return x; return a[x]=fi_a(a[x]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d",&d[i].l,&d[i].r); for(int i=1;i<=n;i++) { fa[0][i]=i; ba[m+1][i]=i; } for(int i=1;i<=m;i++) { memcpy(fa[i],fa[i-1],sizeof fa[i]); int col_x=fi_fa(i,d[i].l); int col_y=fi_fa(i,d[i].r); if(col_x!=col_y) fa[i][col_x]=col_y; } for(int i=m;i>=1;i--) { memcpy(ba[i],ba[i+1],sizeof ba[i]); int col_x=fi_ba(i,d[i].l); int col_y=fi_ba(i,d[i].r); if(col_x!=col_y) ba[i][col_x]=col_y; } scanf("%d",&k); while(k--) { int l,r; scanf("%d%d",&l,&r); memcpy(a,fa[l-1],sizeof a); for(int i=1;i<=n;i++) { int col_x=fi_a(a[i]); int col_y=fi_a(ba[r+1][i]); if(col_x!=col_y) a[col_x]=col_y; } int ans=0; for(int i=1;i<=n;i++) if(a[i]==i) ans++; cout<<ans<<endl; } return 0; }
搞什麼啊,模擬賽就這樣考一道小搜索真的好嗎?
一個高度爲h地點被稱做d-山峯,只有知足從這裏出發,在不通過小於等於h-d的地點的前提下沒法達到比它更高的地方。
簡潔易懂的語言加上500的數據範圍,我彷彿在作普及組QAQ
因此這題就是個時間tag優化bfs。
具體細節看代碼吧 ?
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; int dx[5]={0,0,1,0,-1}; int dy[5]={0,1,0,-1,0}; int n,m,d,tim,maxn; int mp[507][507],vis[507][507]; bool flag; struct node{ int x,y; }; void bfs(int x,int y) { queue<node> q; q.push((node){x,y}); int high=mp[x][y]-d; vis[x][y]=++tim; while(!q.empty()) { node nw=q.front(); q.pop(); for(int i=1;i<=4;i++) { int nwx=nw.x+dx[i]; int nwy=nw.y+dy[i]; if(nwx<1||nwx>n||nwy<1||nwy>m) continue; if(mp[nwx][nwy]<=high||vis[nwx][nwy]==tim) continue; if(mp[nwx][nwy]>mp[x][y]) { flag=1; return; } vis[nwx][nwy]=tim; q.push((node){nwx,nwy}); } } return; } int main() { scanf("%d%d%d",&n,&m,&d); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&mp[i][j]); maxn=max(maxn,mp[i][j]); } } int ans=0; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(mp[i][j]==maxn) continue; bfs(i,j); if(flag) { ans++; flag=0; } } } cout<<n*m-ans<<endl; return 0; }
最後總結一下,其實B組的題仍是蠻水的QAQ
期待下次能夠200+