20161025模拟赛解题报告
T1
官方AC方法:
先按斜率把直线排序,对于每一个三角形,其三条边的斜率必能排序,设斜率为k1<k2<k3,枚举斜率 k2,然后计数 k1 和 k3 的个数,相乘后累加即可。
周边AC方法:
用排列组合搞 -> ans=C(n,3)-ΣC(len[i],2)*(n-len[i])-ΣC(len[i],3)
T2
官方AC方法:
实际上就是求这个序列的最长上升子序列的长度。
简略证明:
假设最长上升子序列长度为 K’,则其中任意两辆丌会进入同一个轨道,因此 K≥K’。至
于 K=K’可由数学归纳法详细证明。
用 O(nlogn)的 DP 方法求最长上升子序列。
周边AC方法:
按题目用O(n)or O(nlogn)模拟即可
T3
官方AC方法:
按照 g 属性从小到大排序。不断加入新边的过程中发现,当前的最小生成树只可能是由未加入新边的最小生成树的边和当前新边组成的共 N 条边中选出 N-1 条构成。因此
维护一个二维最小生成树边集,每次只在 N 条边中做最小生成树,时间复杂度 O(MN)。
周边骗分:
暴力用kruskal去dfs or 枚举可得30-50分
T1代码(100分)
自己的
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define DB double #define ll long long using namespace std; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();} return x*f; } const int N=3e5+10; struct data{int a,b,c;}d[N]; DB K[N]; int n,sq[N],sh[N]; struct node{ DB k; int x; node(DB k=0,int x=0):k(k),x(x){} }f[N]; int main(){ freopen("trokuti.in","r",stdin); freopen("trokuti.out","w",stdout); n=read(); for(int i=1;i<=n;i++) d[i].a=read(),d[i].b=read(),d[i].c=read(); for(int i=1;i<=n;i++){ K[i]=d[i].b==0?1e6:-(DB)d[i].a/(DB)d[i].b; } stable_sort(K+1,K+n+1); memset(f,0,sizeof f); int cnt=0; f[++cnt].k=K[1];f[cnt].x=1; for(ll i=2;i<=n;i++){ if(f[cnt].k!=K[i]) f[++cnt].k=K[i],f[cnt].x=1; else f[cnt].x++; } ll ans=0; for(int i=1;i<=cnt;i++) sq[i]=sq[i-1]+f[i].x; for(int i=cnt;i;i--) sh[i]=sh[i+1]+f[i].x; for(int i=2;i<cnt;i++) ans+=(ll)f[i].x*sq[i-1]*sh[i+1]; cout<<ans; return 0; }
Std的
#include<cstdio> #include<algorithm> #include<iostream> #define ll long long #define pir pair<int,int> #define A first #define B second using namespace std; const int N=3e5+10; bool cmp(const pir &a,const pir &b){ return (ll)a.A*b.B<(ll)a.B*b.A; } pir p[N]; int n,l,r; ll ans; int main(){ freopen("trokuti.in","r",stdin); freopen("trokuti.out","w",stdout); scanf("%d",&n); for(int i=0,x,y;i<n;i++){ scanf("%d%d%*d",&x,&y); p[i]=make_pair(x,y); } sort(p,p+n,cmp); for(int i=0;i<n;i++){ while(cmp(p[l],p[i])) l++; while(r<n&&!cmp(p[i],p[r])) r++; ans+=(ll)l*(n-r); } printf("%I64d",ans); return 0; }
T2代码(100分)
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+10; int n,len,a[N],b[N]; inline const int read(){ register int x=0; register char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x; } int main(){ freopen("manage.in","r",stdin); freopen("manage.out","w",stdout); n=read(); for(int i=1;i<=n;i++) a[i]=read(); b[len=1]=a[1]; for(int i=2,pos;i<=n;i++){ if(a[i]>b[len]){ b[++len]=a[i]; } else{ pos=lower_bound(b+1,b+len+1,a[i])-b; b[pos]=a[i]; } } printf("%d",len); return 0; }
T3代码(100分)
#include<cstdio> #include<algorithm> #define ll long long using namespace std; inline const ll read(){ register ll x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();} return x*f; } const int N=1e5+10; struct node{ int u,v; ll g,s; bool vis; }e[N],tree[N],zan[N]; int n,m,cnt,fa[N]; ll wG,wS,GG,SS; ll ans=999999999999999999LL; bool cmp1(const node &a,const node &b){ if(a.g==b.g) return a.s<b.s; return a.g<b.g; } int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } void MST(ll maxg){ for(int i=1;i<=cnt;i++) zan[i]=tree[i],zan[i].vis=0; ll maxs=0; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1,k=0,fx,fy;i<=cnt;i++){ fx=find(tree[i].u);fy=find(tree[i].v); if(fx!=fy){ fa[fy]=fx; maxs=max(maxs,tree[i].s); zan[i].vis=1; if(++k==n-1){ int p=0; for(int j=1;j<=cnt;j++) if(zan[j].vis) tree[++p]=zan[j]; cnt=p; ans=min(ans,maxg+maxs); return ; } } } } int main(){ freopen("road.in","r",stdin); freopen("road.out","w",stdout); n=read();m=read(); wG=read();wS=read(); for(int i=1;i<=m;i++){ e[i].u=read(),e[i].v=read(),e[i].g=read(),e[i].s=read(); e[i].g*=wG,e[i].s*=wS; } sort(e+1,e+m+1,cmp1); for(int i=1,pos;i<=m;i++){ if(e[i].g+e[i].s>ans) continue; pos=cnt+1; for(int j=1;j<=cnt;j++) if(tree[j].s>e[i].s){pos=j;break;} if(pos>cnt) tree[++cnt]=e[i]; else{ for(int j=++cnt;j>pos;j--) tree[j]=tree[j-1]; tree[pos]=e[i]; } MST(e[i].g); } printf("%I64d",ans); return 0; }