刷題#R8

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

T1
這是一個更相減損。
出現的所有的不同的數就是更相減損過程中出現的;
直接這樣做的話,會T或者爆;
再進一步分析一下,就會發現,我們可以把更相減損優化爲輾轉相除,因爲多幾次更相減損就是輾轉相除,那麼不同數的個數在輾轉相除中就是每次的a/b,因爲a只有減損a/b次纔會達到b,a%b的狀態,這之間的數是遞減的,不會出現重複。

T2
50分,我們可以倒着加邊,添加進新的邊時,用並查集維護,合併集合時,把每個集合新加進的點的個數記下來,這一輪結束後,ans[i]+=ad[i]*ad[i]就可以了。
100分:
用克魯斯卡爾算法求最大生成樹,在並查集合並時,把原本的一個根連向另一
個根改成兩個根都連向一個新建的節點,並把當前正在處理的邊的權值賦給這
個新節點做點權。這樣形成的結構會是一棵樹。
一個點的答案大致上是樹的根到自己的路徑上,相鄰兩個節點的子樹葉節
點數的平方和。需要注意的是父子兩個節點權值相同的情況,這個部分需要特
殊處理。(看代碼會比較容易理解)

T3
不是太會。

T1

#include<iostream> 
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
LL a1,a2,ans;
LL gcd(LL a,LL b)
{
    if(!b) return a;
    ans+=a/b;
    return gcd(b,a%b);
}
int main()
{
    freopen("seq.in","r",stdin);
    freopen("seq.out","w",stdout);
    scanf("%lld%lld",&a1,&a2);
    if(a1<a2) swap(a1,a2);
    gcd(a1,a2);
    ans++;//0也算一種 
    printf("%lld\n",ans);
    return 0;
}

T2
50分

#include<iostream> 
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#define LL long long
using namespace std;
const int N=100009;
const int M=200009;
const int inf=(1e9);
int n,m;
struct H{
    int x,y,z;
}e[M];
int a[M],cnt,f[N];
LL ans[N],siz[N],ad[N]; 
bool cmp(H w1,H w2)
{
    return w1.z>w2.z;
}
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
void add(int o)
{
    int fx=find(e[o].x);
    int fy=find(e[o].y);
    if(fx!=fy)
    {
        for(int i=1;i<=n;i++)
        {
            int ff=find(i);
            if(ff==fx)
              ad[i]+=siz[fy];
            else
            if(ff==fy)
              ad[i]+=siz[fx];
        }
        f[fx]=fy;
        siz[fy]+=siz[fx];
    }
}
int main()
{
    freopen("car.in","r",stdin);
    freopen("car.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;i++) if(e[i].z!=a[cnt]) a[++cnt]=e[i].z; 
    for(int i=1;i<=n;i++) f[i]=i,siz[i]=1;

    int t=1;
    for(int i=1;i<=cnt;i++)
    {
        int flag=0;
        while(e[t].z>=a[i]&&t<=m)
        {
            add(t);
            t++;
            flag=1;
        }
        if(f)
        for(int i=1;i<=n;i++)
        {
            ans[i]+=ad[i]*ad[i];
            ad[i]=0;
        }
        if(t>m) break;
    }   
    for(int i=1;i<=n;i++)
      printf("%lld ",ans[i]);
    return 0;
}

100分(打了一遍找不到了,貼標程吧qaq)

#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;
}
發佈了339 篇原創文章 · 獲贊 240 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章