1. 程式人生 > 實用技巧 >data-2020-11-19

data-2020-11-19

今日模擬賽說實話打得不行。

三道題都會做,但是 T3 寫炸了。

大概從 T3 得出了自己的一些問題:

\(1.\) 樹剖已經開始出現打錯的現象了。

\(2.\) 對於那種需要撤銷,刪除的操作,若有特殊情況需要跳出,必須在跳出前先進行此類操作。

今日寫的題:模擬賽的三道(T2 個人覺得沒有問題,SPJ 鍋了也不好檢驗)。

T1

又是算日期,這次我大概掌握做這種題的套路了,找到合適的迴圈節把資料變小然後直接跑暴力就行了。

T2

考慮 DP, \(f_{i,j}\) 表示到第 \(i\) 個位置,前面一共塞了 \(j\) 個人的最小 low 值,然後這類需要輸方案的 Dp 無非就是記錄一下前驅。

P4180 [BJWC2010]嚴格次小生成樹

寫了一個大常數 \(\log^2\),最後一個點死都卡不過去。

有幾個問題也暴露出來了:

\(1.\) 不少資料結構題我在想到做法之後就基本不會繼續考慮題目本身,而是直接去考慮程式碼實現了,以至於用錯誤複雜度的方法寫半天。

\(2.\) 並查集經常忘記路徑壓縮。(自從 怎樣更有力氣 那道題開始就經常犯這個錯誤)

#include <stdio.h>
#include <vector>
#include <algorithm>
#define LL long long
using namespace std;
const int N=1e5+3;
const int M=3e5+3;
int n,m;
inline void jh(int &x,int &y){x^=y^=x^=y;return;}
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}

struct Rin
{
    char c;
    inline char gc()
    {
        static char rea[M];
        static char *head,*tail;
        return head==tail&&(tail=(head=rea)+fread(rea,1,M,stdin),head==tail)?EOF:*head++;
    }
    inline Rin&operator >>(int &x)
    {
        x=0;
        bool bj=false;
        for(c=gc();c>'9'||c<'0';c=gc())if(c=='-'){c=gc();bj=true;break;}
        for(;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c^'0');
        if(bj)x=-x;
        return *this;
    }
    inline Rin&operator <<(LL x)
    {
        static char a[66];
        static int tail;
        if(!x)putchar(48);
        else
        {
            tail=0;
            if(x<0){x=-x;putchar('-');}
            for(;x;x/=10)a[++tail]=x%10;
            for(;tail;tail--)putchar(a[tail]+48);
        }
        putchar('\n');
        return *this;
    }
}rin;

int F[N];
inline int find(int x){return (F[x]==x)?(x):(F[x]=find(F[x]));}

struct cow
{
    int y,z;
    cow(int y_,int z_){y=y_;z=z_;return;}
};
vector<cow>to[N];

struct milk
{
    int x,y,z;
    bool bj;
    inline void add(){to[x].push_back(cow(y,z));to[y].push_back(cow(x,z));bj=true;return;}
}a[M];
int c[M];
int psc;
inline bool myru_a(milk x,milk y){return x.z<y.z;}
inline bool myru_b(int x,int y){return a[x].z<a[y].z;}

struct zjj
{
    int ls,rs;
    int s;
}t[N*25];
int st[N];
int cutt;
inline void make_tree(int l,int r,int i)
{
    t[i].ls=t[i].rs=t[i].s=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    make_tree(l,mid,t[i].ls=++cutt);
    make_tree(mid+1,r,t[i].rs=++cutt);
    return;
}
inline void add_tree(int l,int r,int now,int last,int s)
{
    t[now]=t[last];t[now].s++;
    if(!t[now].ls)return;
    int mid=(l+r)>>1;
    if(mid>=s)add_tree(l,mid,t[now].ls=++cutt,t[last].ls,s);
    else add_tree(mid+1,r,t[now].rs=++cutt,t[last].rs,s);
    return;
}

struct prpr
{
    int fa;
    int dep;
    int top;
}T[N];
int num[N];
int son[N];
int lar[N];
int val[N];

int nam;
inline void dfs_down(int now,int fa)
{
    lar[now]=1;
    int maxl=0;
    for(int i=to[now].size()-1;i>=0;i--)
    {
        int y=to[now][i].y,z=to[now][i].z;
        if(y==fa)continue;
        val[y]=z;dfs_down(y,now);lar[now]+=lar[y];
        if(lar[y]>maxl)son[now]=y;
    }
    return;
}
inline void add_list(int now){T[nam+1].fa=num[now];T[nam+1].dep=T[num[now]].dep+1;return;}
inline void make_list(int now,int fa)
{
    num[now]=++nam;
    add_tree(1,psc,st[nam]=++cutt,st[nam-1],val[now]);
    T[nam].top=num[fa];
    if(!son[now])return;
    add_list(now);make_list(son[now],fa);
    for(int i=to[now].size()-1;i>=0;i--)if(!num[to[now][i].y])add_list(now),make_list(to[now][i].y,to[now][i].y);
    return;
}

inline int cheak_rank(int l,int r,int now,int last,int v)
{
    if(t[now].s-t[last].s==0)return 0;
    if(r<v)return t[now].s-t[last].s;
    if(l>=v)return 0;
    int mid=(l+r)>>1;
    if(mid<v)return t[t[now].ls].s-t[t[last].ls].s+cheak_rank(mid+1,r,t[now].rs,t[last].rs,v);
    else return cheak_rank(l,mid,t[now].ls,t[last].ls,v);
}
inline int cheak_num(int l,int r,int now,int last,int s)
{
    if(!t[now].ls)return c[l];
    int now_s=t[t[now].ls].s-t[t[last].ls].s;
    int mid=(l+r)>>1;
    if(now_s>=s)return cheak_num(l,mid,t[now].ls,t[last].ls,s);
    else return cheak_num(mid+1,r,t[now].rs,t[last].rs,s-now_s);
}
inline int cheak_(int l,int r,int v){return cheak_num(1,psc,st[r],st[l-1],cheak_rank(1,psc,st[r],st[l-1],v));}
inline int work(int now)
{
    int x=num[a[now].x],y=num[a[now].y];
    int sum=-0x3f3f3f3f;
    for(;T[x].top!=T[y].top;)
    {
        if(T[T[x].top].dep<T[T[y].top].dep)jh(x,y);
        sum=max(sum,cheak_(T[x].top,x,a[now].z));
        x=T[T[x].top].fa;
    }
    if(T[x].dep<T[y].dep)jh(x,y);
    if(x!=y)sum=max(sum,cheak_(y+1,x,a[now].z));
    return c[a[now].z]-sum;
}
int main()
{
    int i,j;
    rin>>n>>m;
    for(i=1;i<=m;i++){rin>>a[i].x>>a[i].y>>a[i].z;a[i].bj=false;}
    sort(a+1,a+m+1,myru_a);
    for(i=1;i<=m;i=j){c[++psc]=a[i].z;for(j=i;j<=m&&a[j].z==c[psc];j++)a[j].z=psc;}
    LL ans=0;
    for(i=1;i<=n;i++)F[i]=i;
    for(i=1;i<=m;i++)if(find(a[i].x)!=find(a[i].y))F[find(a[i].x)]=find(a[i].y),a[i].add(),ans+=c[a[i].z];
    make_tree(1,psc,st[0]=++cutt);
    dfs_down(1,0);T[1].dep=1;make_list(1,1);
    int mins=0x3f3f3f3f;
    for(i=m;i>=1;i--)if(!a[i].bj)if(c[a[i].z]-c[a[i].z-1]<mins)mins=min(mins,work(i));
    ans+=mins;
    rin<<ans;
    return 0;
}