JNday4-pm
预计分数 A + 30 + 0
实际分数 70 + 30 + 0
T1
这道题感觉并不难,先写出了暴力,对照暴力自己yy了差不多1h,调了出来,
然而没有写对拍,
正解:
这个东西的本质是更相减损术,相当于每次减去较小的那个数,然而直接进行
更相减损术太慢,我们可以通过辗转相除法来加快这个进程,并且在辗转相除
时累加答案
T2
当时做时并没有多长时间,相当于直接放弃了
kruscal算法求最大生成树,在并查集合并时,把原本的一个根连向另一个根
改成两个根都连向一个新建的节点,并把当前正在处理的边的权值赋给这个新建
节点做点权,这样形成的结构会是一课时,一个点的answer大致上是树的根到自己的
路径上,相邻两个节点的子树叶节点数的平方和。需要注意的是,父子两个节点权值
相同的情况,这个部分需要特殊处理。
T3
没听懂。。。。
T1 数列
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll a,b,c,ans; int main(){ freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); scanf("%lld%lld",&a,&b); if (a<b) swap(a,b); c = a%b; while (c){ ans += a/b; a = b;b = c;c = a%b; } ans += a/b; ans++; printf("%lld\n",ans); return 0; }
T2 车辆销售
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N = 510000; typedef long long ll; struct node { int u, v, l; bool operator < (const node &no) const { return l > no.l; } }e[N]; int n, m, newn; int son[N][2]; int fa[N], size[N], value[N]; ll ans[N]; int read() { char ch = getchar(); int x = 0; while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) {x = x*10+(ch-'0');ch=getchar();} return x; } int getf(int x) { if (fa[x] == x) return x; fa[x] = getf(fa[x]); return fa[x]; } void dfs(int u, int fa, ll cnt) { ll delta = 0; if (fa) { if (value[u] == value[fa]) size[u] = size[fa]; else delta = (ll)(size[fa] - size[u]) * (ll)(size[fa] - size[u]); } if (son[u][0]) { dfs(son[u][0], u, cnt + delta); dfs(son[u][1], u, cnt + delta); } else ans[u] = cnt + delta; } int main() { freopen("car.in","r",stdin); freopen("car.out","w",stdout); n = read(), m = read(); for (int i = 1; i <= m; i++) { e[i].u = read(); e[i].v = read(); e[i].l = read(); } sort(e + 1, e + 1 + m); for (int i = 1; i <= n; i++) fa[i] = i; newn = n; for (int i = 1; i <= n; i++) size[i] = 1; for (int i = 1; i <= m; i++) { int u = getf(e[i].u), v = getf(e[i].v); if (u == v) continue; newn++; son[newn][0] = u; son[newn][1] = v; fa[u] = fa[v] = newn; fa[newn] = newn; value[newn] = e[i].l; size[newn] = size[u] + size[v]; } dfs(newn, 0, 0); for (int i = 1; i <= n; i++) printf("%lld ", ans[i]); printf("\n"); return 0; }
T3 取数
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long LL; const int N=1000010; const LL inf=10000000; int n,m,x,y,z,L,sum; int cnt[N]; LL ans0,ans; LL f[N],s[N]; LL read() { LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void solve(LL c) { int i,a,tot=0; LL ss=0; memset(cnt,0,sizeof(cnt)); memset(f,0,sizeof(f)); for(i=1;i<=n;i++) { a=i-m; if(a>=1&&c-s[a]>0&&(f[a]>ss||(f[a]==ss&&cnt[a]<tot))) { ss=f[a]; tot=cnt[a]; } if(c-s[i]>0) { f[i]=ss+c-s[i]; cnt[i]=tot+1; } } ans0=sum=0; for(i=1;i<=n;i++) if(f[i]>ans0||(f[i]==ans0&&sum>cnt[i])) { sum=cnt[i]; ans0=f[i]; } // printf("%d %lld %lld\n",sum,c,ans0); } int pd(LL c) { solve(c); if(sum<L) return 1; else return 0; } int main() { int a,b,c,i,j,k; LL l,r; freopen("number.in","r",stdin); freopen("number.out","w",stdout); n=read(); m=read(); L=read(); for(i=1;i<=n;i++) s[i]=read(); // for(i=1;i<=n;i++) // if(i%m==1) ans+=(LL)s[i]; // printf("%lld\n",ans); ans=0; l=0; r=(LL)inf*N/2; while(l<r-1) { LL mid=(l+r)/2; if(pd(mid)) l=mid; else r=mid; } if(pd(r)) { solve(r); ans=(LL)L*r-ans0; // printf("%d\n",sum); } else { solve(l); ans=(LL)L*l-ans0; } printf("%lld\n",ans); } /* 6 5 2 100 1 1 1 1 100 */