Noip模擬題解題報告
阿新 • • 發佈:2018-12-12
Pro
Sco
預計得分:
實際得分:
被第三題給虐了,打了一份不是正解卻自以為正解的程式碼……
Sol
三角形
測完之後才明白我原來用了一個比較麻煩的解法,不過還好AC了……
因為沒有三線共點,所以我們可以得到:任何三條相交的直線都可以構成一個三角形
如果全部都不平行,可以構成 個三角形
任意兩兩平行都不能構成三角形,任意三條平行線也不能構成三角形
於是答案即為:
其中,為平行線的組數,為平行線的條數。
組合數可以預處理出來,平行線可以用斜率來做。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int L = 300005; double k[L] , temp; int n , cnt[L] , opt; long long C2[L] , C3[L] , ans; void init() { sort(k+1 , k+n+1); temp = k[1]; opt = 1; cnt[opt] = 1; for(int i=2; i<=n; i++) { if(k[i] == temp) cnt[opt]++; else { opt++; cnt[opt] = 1; temp = k[i]; } } for(int i=1; i<=n; i++) { C2[i] = (long long)((long long)(i-1)*i)/2; C3[i] = (long long)((long long)(i-2)*(i-1)*i)/6; } } int main() { freopen("trokuti.in","r",stdin); freopen("trokuti.out","w",stdout); scanf("%d",&n); for(int i=1; i<=n; i++) { int a , b , c; scanf("%d%d%d",&a,&b,&c); if(b!=0) k[i] = -(1.0*a/b); else k[i] = 1e9; } init(); ans = C3[n]; for(int i=1; i<=opt; i++) { long long data = (n-cnt[i])*C2[cnt[i]] + C3[cnt[i]]; ans -= data; } printf("%lld",ans); return 0; }
列車排程
很裸~~(shui)~~的一個……
(手動模擬一下就可以發現是一個最大上升子序列,我直接打了的。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n , num[100005] , res[100005] , ans; inline int mymax(int a , int b) { return a>b?a:b; } int main() { freopen("manage.in","r",stdin); freopen("manage.out","w",stdout); scanf("%d",&n); memset(res , 0x3f , sizeof(res)); for(int i=1; i<=n; i++) scanf("%d",&num[i]); res[1] = num[1]; for(int i=2; i<=n; i++) { int opt = lower_bound(res+1 , res+n+1 , num[i]) - res; res[opt] = num[i]; ans = mymax(ans , opt); } printf("%d",ans); return 0; }
保留道路
第一次的保齡程式碼竟然想到了二分!恐怖.jpg
後來才發現之前的想法就有錯誤。
直接按照從小到大排序,維護一個最小生成樹的邊集。
資料規模不大,每一次都克魯斯卡爾判斷是否聯通,時間複雜度
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Road {
long long from , to , g , s , vis;
};
Road e[50005] , tree[50005] , temp[50005];
long long n , m , WG , WS , cnt , fa[405] , ans = 1e18;
inline long long mymax(long long a , long long b) { return a>b?a:b; }
inline long long mymin(long long a , long long b) { return a<b?a:b; }
bool cmp(Road a , Road b) {
if(a.g == b.g)
return a.s < b.s;
return a.g < b.g;
}
long long find(long long x) {
if(fa[x] != x)
return find(fa[x]);
return fa[x];
}
void klus(long long mg) {
long long ms = 0 , tot = 0;
for(long long i=1; i<=cnt; i++) {
temp[i] = tree[i];
temp[i].vis = false;
}
for(long long i=1; i<=n; i++)
fa[i] = i;
for(long long i=1; i<=cnt; i++) {
long long fx = find(tree[i].from) , fy = find(tree[i].to);
if(fx != fy) {
ms = mymax(ms , tree[i].s);
fa[fx] = fy;
tot++;
temp[i].vis = true;
}
if(tot == n-1) {
long long pot = 0;
for(int j=1; j<=cnt; j++)
if(temp[j].vis)
tree[++pot] = temp[j];
cnt = pot;
ans = mymin(ans , ms+mg);
break;
}
}
}
int main() {
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
scanf("%lld%lld%lld%lld",&n,&m,&WG,&WS);
for(long long i=1; i<=m; i++) {
scanf("%d%d%lld%lld",&e[i].from,&e[i].to,&e[i].g,&e[i].s);
e[i].g = (long long)e[i].g * WG;
e[i].s = (long long)e[i].s * WS;
}
sort(e+1 , e+m+1 , cmp);
for(int i=1; i<=m; i++) {
if(e[i].g + e[i].s > ans)
continue;
long long opt = cnt + 1;
for(int j=1; j<=cnt; j++)
if(e[i].s < tree[j].s) {
opt = j;
break;
}
if(opt == cnt + 1)
tree[++cnt] = e[i];
else {
for(int j=++cnt;j>=opt+1;j--)
tree[j]=tree[j-1];
tree[opt]=e[i];
}
klus(e[i].g);
}
printf("%lld",(ans==1e18)?(-1):ans);
return 0;
}