Full_of_Boys训练1总结
題目來源:?2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)
A. Archery Tournament
每次查詢,找這個位置前面的15個圓,后邊15個圓來更新答案。set維護一下圓就行。為什么對,官方題解:可以證明經過某一條豎線的圓不超過logC個(C=1e9)
#include <bits/stdc++.h> #define pb(x) push_back(x) const int maxn = 200000+5; const int lim = 15; typedef long long ll; using namespace std; int n; struct qq{int opt;ll x,y;}Q[maxn]; struct node{int id;ll x,y;node(){}node(ll a,ll b,int c){x=a;y=b;id=c;}bool operator < (const node a)const{if(a.x==x)return y < a.y;return x < a.x;} }; set<node>s; set<node>::iterator it,it1; ll dis(ll x1,ll y1,ll x2,ll y2){return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); } ll in_cir(ll x1,ll y1,ll x2,ll y2){if(dis(x1,y1,x2,y2)<y1*y1)return 1;return 0; } int main() {scanf("%d",&n);for(int i=1;i<=n;++i){int opt;ll x,y;scanf("%d%I64d%I64d",&opt,&x,&y);Q[i].opt=opt;Q[i].x=x;Q[i].y=y;}for(int i=1;i<=n;++i){if(Q[i].opt==1)s.insert(node(Q[i].x,Q[i].y,i));else{int cc=0,ans=-1;it = s.lower_bound(node(Q[i].x,0,0));for(;it!=s.end()&&cc<=lim;++cc,++it){if(in_cir((*it).x,(*it).y,Q[i].x,Q[i].y)){s.erase(it);ans=(*it).id;break;}}cc=0;it1=s.lower_bound(node(Q[i].x,0,0));for(;it1!=s.begin()&&cc<=lim;--it1,++cc){if(in_cir((*it1).x,(*it1).y,Q[i].x,Q[i].y)){s.erase(it1);ans=(*it1).id;break;}}it1=s.begin();if(in_cir((*it1).x,(*it1).y,Q[i].x,Q[i].y)){s.erase(it1);ans=(*it1).id;}printf("%d\n",ans);}}return 0; }反思:這種重圓不多,現場猜測到了。。。xi ka xi。。。我的思路是直接將,每個圓包含的關鍵點暴力的加上,這個圓的標記,會Mle,但應該不會Tle,隊友說線段樹,當場只想到一種比暴力還糟的做法。。。下來思考了一下,既然直接暴力mle,那我分塊暴力。每個塊維護一個set存圓,然后添加和刪除圓,就直接更新這個圓覆蓋過的塊。對于查詢,每次暴力這個塊和他左右兩邊的塊。??后來覺得不對,畢竟按橫坐標分塊暴力,直覺上無法保證復雜度。那可不可以在塊內二分出那個橫坐標最近的圓?然后小范圍暴力一下?那還分啥塊?一個set就搞定了?后來,看了下題解發現小范圍暴力,是有正確性的。艱難AC。。。另一種思路,我們分塊到底?既然不能按橫坐標分塊,那就按照圓分塊?這樣每個圓內最多有3*√n個x坐標?復雜度還很穩定。思考一下,發現如果不用這個結論,還是沒有特別真的做法。。。還是直接set做吧。223
現場時,腦子就跟掛機了一樣,下來分析一下,感覺并不是一道不可做的題。這是辣雞RRRR_wys長期的問題。。。希望有高人,能指點一下,如何保證現場賽腦子在線。。。
B. Box
分類討論
#include <bits/stdc++.h> using namespace std; int a[3],w,h,ww,hh; bool ck1(){ww=a[1]*2+a[2]*2;hh=a[0]+a[2]*2;if(ww<=w&&hh<=h)return 1;ww=a[1]*2+a[2]*2;hh=a[0]+a[1]+a[2];if(ww<=w&&hh<=h)return 1;ww=a[0]+a[1]+a[2]*3;hh=a[0]+a[1];if(ww<=w&&hh<=h)return 1;ww=a[0]+a[1]+a[2]*2;hh=a[0]+a[1]+a[2];if(ww<=w&&hh<=h)return 1;ww=a[0]+a[1]*2+a[2];hh=a[0]+a[2]*2;if(ww<=w&&hh<=h)return 1;ww=a[0]*2+a[1]+a[2];hh=a[0]+a[1]+a[2];if(ww<=w&&hh<=h)return 1;ww=a[0]*2+a[1];hh=a[0]+a[1]+a[2]*2;if(ww<=w&&hh<=h)return 1;return 0; } bool ck(){sort(a,a+3);for(int ti=0;ti<6;++ti){if(ck1())return 1;next_permutation(a,a+3);}return 0; } int main() {scanf("%d%d%d%d%d",&a[0],&a[1],&a[2],&w,&h);if(ck()){puts("Yes");return 0;}swap(w,h);if(ck()){puts("Yes");return 0;}puts("No");return 0; }C. Connections
題意可以理解為:求一些有向邊使得整張圖是一個強連通圖。刪除這些分量中的邊就是答案。根據一種貪心的構造,最多加入2(n-1)條邊,一定可以使得整張圖強連通。相當于一顆樹,它的每一條邊都是雙向邊。那么就可以通過Kosaraju算法,處理出在強聯通分量中的邊做了。
#include <bits/stdc++.h> #define pb(x) push_back(x) typedef long long ll; const int maxn = 300000+7; using namespace std; int n,m; struct edge{int u,v,nxt;}E[maxn][2]; int h[maxn][2],cc; void add(int u,int v){++cc;E[cc][0].u=u;E[cc][0].v=v;E[cc][0].nxt=h[u][0];h[u][0]=cc;E[cc][1].u=v;E[cc][1].v=u;E[cc][1].nxt=h[v][1];h[v][1]=cc; } bool vis[maxn],used[maxn];int stc[maxn],tp; void dfs1(int u){vis[u]=1;for(int i=h[u][0];~i;i=E[i][0].nxt){int v=E[i][0].v;if(!vis[v]){used[i]=1;dfs1(v);}}stc[++tp]=u; } void dfs2(int u){vis[u]=0;for(int i=h[u][1];~i;i=E[i][1].nxt){int v=E[i][1].v;if(vis[v]){used[i]=1;dfs2(v);}} } int T; int main() {scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);cc=tp=0;memset(h,-1,sizeof(h));memset(used,0,sizeof(used));for(int i=1;i<=m;++i){int x,y;scanf("%d%d",&x,&y);add(x,y);}for(int i=1;i<=n;++i)if(!vis[i])dfs1(i);for(int i=n;i>=1;--i)if(vis[stc[i]])dfs2(stc[i]);int tn = 2*n;for(int i=1;i<=m;++i)if(used[i])--tn;for(int i=1;i<=m;++i)if(!used[i]&&tn>0)--tn,used[i]=1;for(int i=1;i<=m;++i)if(!used[i]){printf("%d %d\n",E[i][0].u,E[i][0].v);}}return 0; }反思:做這道題的時候,看到榜上ac人數較多,就猜測是個計算度數,然后胡亂貪心,wa掉之后,依然不死心,導致gg。zyc賽中提到一種,一邊判環縮環,記錄邊數的做法(有問題)。并沒有被我重視。。。仔細考慮一下,就會發現這個思路與強聯通相似之處,Kosaraju算法通過在第一次dfs的標記的順序,進行第二次dfs,使得我們不會指向多余的邊(感覺上......不會證明)。胡思亂想坑隊友。。。
?D. Designing the Toy
E. Easy Quest
F. The Final Level
G. The Great Wall
H. Hack
I. Interactive Sort
J. Journey from Petersburg to Moscow
K. Knapsack Cryptosystem
L. Laminar Family
把每條路徑按照長度降序排列,每次隨機一個值把他異或到整個路徑上,然后查詢這個路徑是否所有數字都相同即可。實現方法,先樹剖,用線段樹區間間異或,區間詢問是否所有數全部相同,為了完成合并,還要維護區間左右端點的值??墒?#xff0c;wa在test26 。。。各位聚聚,能不能給施舍弱幾組數據。。。wa的:https://paste.ubuntu.com/p/dy4sBzXrVZ/
-------------------------------------------------------------------------------------------2018/04/27 更新
之后,想了一下,為什么要用區間異或,這種東西呢?排序之后,直接區間賦值,存下數字不同的兩個位置,當給定區間包含某一對這樣的位置時,區間數字就不相同。這個直接開個set在里面二分第一個大于左端點的左點,check一下就行了。嘴完了。。。
感覺不對。。。涼了。
?
轉載于:https://www.cnblogs.com/RRRR-wys/p/8879075.html
總結
以上是生活随笔為你收集整理的Full_of_Boys训练1总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FFT算法学习笔记
- 下一篇: Full_of_Boys训练2总结