發表文章

目前顯示的是 6月, 2017的文章

[TIOJ] 1732. 買當勞

題目連結: http://tioj.infor.org/problems/1732 應該不難發現買當勞要建的位置就是所有資料的中位數,所以就排個序就可以找到了,複雜度$O(n log n)$ #include <bits/stdc++.h> using namespace std; #define N 100000 int arr[N+5]; int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n; while(cin>>n){ for(int i=0;i<n;i++) cin>>arr[i]; sort(arr, arr+n); int mid; if(n&1) mid=arr[n>>1]; else mid = (arr[n>>1]+arr[(n>>1) - 1])>>1; int ans=0; for(int i=0;i<n;i++) ans+=abs(arr[i]-mid); cout<<ans<<'\n'; } return 0; } 不過突然看到聖福學長用超快的作法過了這題,想了三十秒才發現其實根本可以用nth_element做到$O(n)$的複雜度 #include <bits/stdc++.h> using namespace std; #define N 100000 int arr[N+5]; int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n; while(cin>>n){ for(int i=0;i<n;i++) cin>>arr[i]; ...

[TIOJ] 1088. [Interactive] 取石頭(二)

題目連結: http://tioj.infor.org/problems/1088 標準的nim遊戲。本題如果知道nim的玩法應該就秒解了,因為nim的遊戲方法就是讓所有數xor起來為零,因為當一個人拿到xor直為零的時候他必定沒辦法再讓版面的xor值為零,而且你也一定可已把盤面xor值弄成零,所以就看兩下吧XD p.s附個我寫的lib1088.h lib1088.h #include <cstdio> int __stones[3]; void Initialize(int *a,int *b,int *c){ printf("How many stones:"); scanf("%d%d%d",a,b,c); __stones[0]=*a;__stones[1]=*b;__stones[2]=*c; } void Take_Stone(int pile_no, int num, int *com_pile, int *com_num){ __stones[pile_no-1]-=num; printf("Now: "); for(int i=0;i<3;i++) printf("%d ",__stones[i]); puts(""); bool flag=1; for(int i=0;i<3;i++) if(__stones[i]>0)flag=0; if(flag){ puts("You Lose!"); exit(0); } printf("Chosse and sum:"); scanf("%d%d",com_pile, com_num); __stones[(*com_pile)-1]-=(*com_num); for(int i=0;i...

[TIOJ] 1137. 4.收費站設置問題

題目連結: http://tioj.infor.org/problems/1137 應該不難看出來題目就是在求一個點使得拔掉後會讓兩個區塊不連通,那這正好就是關節點。而關節點的求法是什麼呢?這裡採用tarjan的算法: 在以某一特定點DFS的情況下,會長出一個類似樹的部分,只不過有些邊會連回上面,也就是樹上不該有的邊,這裡稱其為「回邊」,而正常定義的樹上會有的邊,這裡稱其為「樹邊」。 接著,定義一種值$ low(x), x \in V$其中V為所有點的點集,low(x)為點x不透過連接自己的樹邊,所能到達的深度的最小值(往上最遠可以到哪),仔細觀察後發現,當一個點p的小孩中,有一個點q的low值$ \leq $自己的深度,意即其必須透過p才能回到上面,那明顯p就會是一個關節點(因為拔掉p之後q就會與一些人不連通了),不過特別注意一下根的部分,因為顯然所有人的low值都$ \leq $根的深度,但是根不一定關節點,細想一下後會發現根不是關節點的條件為他只有一個小孩的時候,那到這裡算法的架構就大概完整了。 至於low值維護的方式就是邊dfs邊用類似dp的方式維護即可了。 #include <bits/stdc++.h> using namespace std; #define N 10000 vector<int> graph[N+5]; int low[N+5]; bool visited[N+5]; set<int> ap; void dfs(int,int,int); int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int t;cin>>t; while(t--){ ap.clear();fill(visited, visited+N+5, false); int n,m;cin>>n>>m; for(int i=0;i<m;i++){ int st,ed;cin>>s...

[TIOJ] 1559. Mikey的數學作業

題目連結: http://tioj.infor.org/problems/1559 數學不好,想了一下下。我的作法是求出給定兩個點的距離跟夾角,之後以其中一個點為暫時原點,然後用極座標轉回普通座標方式的作法找到60度的點,再平移回剛剛的暫時原點即可。 #include <bits/stdc++.h> using namespace std; typedef pair<double,double> PDD; #define X first #define Y second #define deg2rad(x) (acos(-1)*x/180.) int main(){ PDD a,b, ans1, ans2; while(cin>>a.X>>a.Y>>b.X>>b.Y){ double dis = sqrt((a.X-b.X)*(a.X-b.X)+(a.Y-b.Y)*(a.Y-b.Y)); double theta = atan2((b.Y-a.Y), (b.X-a.X)); ans1 = {a.X+dis*cos(deg2rad(60)+theta), a.Y+dis*sin(deg2rad(60)+theta)}; ans2 = {a.X+dis*cos(deg2rad(300)+theta), a.Y+dis*sin(deg2rad(300)+theta)}; if(ans2<ans1) swap(ans1,ans2); cout<<setprecision(3)<<fixed<<ans1.X<<' '<<ans1.Y<<' '<<ans2.X<<' '<<ans2.Y<<'\n'; } return 0; }

[TIOJ] 1586. 新年快樂 Happy New Year!

題目連結: http://tioj.infor.org/problems/1586 照著做就好了,練習scanf跟printf #include <cstdio> int main(){ int n;scanf("%d",&n); while(n--){ char s[60]; scanf("%s",s); printf("%s, happy new year!!!\n",s); } return 0; }

[TIOJ] 1679. 抽紙牌(poker)

題目連結: http://tioj.infor.org/problems/1679 把東東吃進來後排序並取到要取的位置即可,而且C++中有個東西叫做pair,他比大小自動就是先比第一項再比第二項 #include <bits/stdc++.h> using namespace std; typedef pair<int,char> PCI; #define N 52 PCI cards[N]; int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n;cin>>n; for(int i=0;i<n;i++) cin>>cards[i].second>>cards[i].first; sort(cards,cards+n,[](PCI a, PCI b){return a>b;}); int m;cin>>m; cout<<cards[m-1].second<<' '<<cards[m-1].first; return 0; }

[TIOJ] 1657. 小明最喜歡作弊

題目連結: http://tioj.infor.org/problems/1657 兩層for迴圈,裸裸的做就好了 #include <bits/stdc++.h> using namespace std; int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n,m; while(cin>>n>>m){ for(int i=1;i<=n;i++){ for(int j=1;j<m;j++) cout<<i<<'*'<<j<<'='<<i*j<<' '; cout<<i<<'*'<<m<<'='<<i*m<<'\n'; } } return 0; }

[TIOJ] 1745. [APIO '10] Commando

題目連結: http://tioj.infor.org/problems/1745 這題應該不難想到DP的方式\[ f(x) =ax^2+bx+c \\ dp[i] = \max_{0 \leq j #include <bits/stdc++.h> using namespace std; typedef long long lld; #define INF 2147483647 #define N 1000000 lld a,b,c; lld arr[N+5], sm[N+5], dp[N+5]; inline bool detectBeyond(int,int,int); inline lld f(int,int); int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n;cin>>n; cin>>a>>b>>c; for(int i=1;i<=n;i++){ cin>>arr[i]; sm[i]=arr[i]+sm[i-1]; } for(int i=1;i<=n;i++)dp[i]=-INF; deque<int> dq; dq.push_back(0); for(int i=1;i<=n;i++){ while(dq.size()>1 && f(dq[0], i) < f(dq[1], i)) dq.pop_front(); dp[i] = f(dq[0], i) + a*sm[i]*sm[i]+b*sm[i]+c; while(dq.size()>1 && detectBeyond(dq[dq.size()-2], dq[dq.size()-1], i)) dq.pop_back();...

[TIOJ] 1142. 3.關鍵邏輯閘

題目連結: http://tioj.infor.org/problems/1142 笨笨的我完全想不出來該怎麼寫...最後是被雷了才知道的QAQ。不過明顯有幾個點大家應該早就知道,本題其實就是要找最長路,並且看該路上有幾個節點,且如果有兩個人權重相同,則兩個人都要走,因此不妨先求出走到每個點所要花的時間,再從最大的開始dfs回去,這裡為了方便,弄了一個假節點,與所有點連接,這樣比較方便在dfs回去時看誰最大 #include <bits/stdc++.h> using namespace std; #define N 100000 #define PB push_back int val[N+5], deg[N+5], valSm[N+5], cnt=0; vector<int> graph[N+5], rgraph[N+5]; bitset<N+5> visited; void dfs(int); int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n, m;cin>>n>>m; for(int i=1;i<=n;i++){ cin>>val[i]; valSm[i]=val[i]; } for(int i=0;i<m;i++){ int st, ed;cin>>st>>ed; deg[ed]++; graph[st].PB(ed); rgraph[ed].PB(st); } for(int i=1;i<=n;i++) rgraph[N+2].PB(i); queue<int> qq; for(int i=1;i<=n;i++) if(deg[i]==0) qq.push(...