「2019.7.29 考試」什么都無法舍棄的人什么也無法改變


  總的來說是比較失敗的一次考試,兩個半小時死剛T1,剩下不到四十分鍾寫T3,很倉促,爆了0。時間分配嚴重不均勻導致T3雖然想到了部分解法但是沒有來得及實現和調試。

  大概考試過程就是先看了三道題,發現T3很簡單,然后開始想,三分鍾秒掉式子,大概7:22的時候就切掉了(事實證明它除了一個特判的確切掉了,而且才開考7分鍾我還看了表)。然后回去看第一題,發現貢獻分了兩半,矩形內部和矩形之間的,矩形內部可以$O(1)$得到,矩形之間的可以$O(n^2)$算出來,但是不是嚴格$O(n^2)$,因為矩形之間的臨接邊很少,沒有的時候就跳就可以了。結果寫了二十分鍾過不了大樣例,當時絕望了,調試的時候發現矩形越多數值越小我就很納悶,但是最終也沒調出來(其實是矩形邊界處理出了問題,出現了負數)。於是去做T2,基本也是秒出解(雖然不太完善但基本和正解差不多,除了合並方式上),然后十分鍾敲了兩顆樹開始維護,只過了小樣例,還是大的過不去,一直調到考試結束,於是T3愉快爆0。

  下面是題解,但是這個東西仿佛不是這次考試最重要的收獲,我覺得應該是一些關於心態方面的啟發,這些我會在最后說。

T1:

  是真的暴力分情況而且沒水平我實在懶得寫

  貢獻分兩部分,

  內部貢獻=$ 2(x2-x1)(y2-y1) $

  邊界貢獻=$ 2(邊界長度)+[一端坐標不一樣]+[另一端坐標不一樣] $

  暴力枚舉加起來即可,到沒有邊界的時候$break$掉即可

 

T2:

  比較強的一道題,考場上想到了時間軸建樹,想到了二分$size$查排名前$k$的數,想到了合並(假的線段樹合並,應該是啟發式合並)。

  想了很久一直沒有結果,因為我的線段樹合並是以不遍歷全部節點為復雜度保障,但是合並了之后又無法斷定哪些點是具有貢獻的,這讓我很難受,最后我取了暴力的方法,暴力查哪些節點是被重復計算的,貢獻置0,但是會重復計算,比如說在某一個子樹的時候某個時間的已經被計算過是無用的,那么接下來子樹合並的過程中,他永遠不可能繼續有用,那么就可以不查了,但是我考場上沒有想到這一點,也許這樣可以挽救我死了的線段樹合並思路。

  剩下的就是啟發式合並了。合並什么呢?我們不合並線段樹,合並操作,或許你覺得這很暴力,但是他有一定的復雜度保證$(O(nlog_2n))$。

  啟發式合並其實很簡單,就是把小的塞到大的里面,這樣的話可以使得代價降到最低,復雜度怎么來的呢?假設我們每次合並的復雜度是$(O(n))$,而最劣的情況就是我每次拿一個和你一樣大的塞你,這樣我每次增大一倍,也就是會增加$(log_2n)$次,那么總的復雜度就是$O(nlog_2n)$

  復雜度是有保障的,那么怎么合並呢?考慮樹上的“大”是什么意思。頹了一篇很不詳細的題解就明白了。對,是重兒子。重兒子是你最大的子樹,其他的子樹在處理完成之后直接在線段樹上打標記刪除掉即可,而重兒子萬萬不能刪除,因為你的操作要建立在重兒子的基礎上操作,這樣能夠保證復雜度。

  我當時沒有想到維護線段樹的方式這么暴力。。。

  把自己的操作插入重兒子的$vector$(一般情況下重兒子操作比我身上的要多,畢竟我就一個節點)然后交換位置,再把其他輕兒子的操作插入我的$vector$,這樣完成了多次啟發式合並,復雜度保證是$O(nlog_2n)$。

  剛才突然想了一下,輕重划分不應當以字節點的大小作為划分依據,而應當用子節點$vector$大小,他快了$100ms$。

  而每次操作都對應線段樹的一次修改或者刪除。

  總復雜度就是$O(nlog_2^2n)$

  每次遞歸的進行這個過程,就可以完美解決這道題。

  說的比較潦草,不懂評論區。

 

#include<cstdio>
#include<cmath>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
const int maxn=1e5+5,INF=0x3f3f3f3f;
map<int,int> mp;
vector<int> bl[maxn],dr[maxn];
int n,m,q,cnt,tot,x,y,a[maxn],first[maxn],ans[maxn],sz[maxn],son[maxn],t[maxn];
struct road{
    int u,t,nxt;
}eage[maxn<<1];
void add(int x,int y)
{
    eage[++tot].u=x;
    eage[tot].t=y;
    eage[tot].nxt=first[x];
    first[x]=tot;
}
struct SegmentTree{
    int tot,data[maxn<<2],sz[maxn<<2],f[maxn<<2];
    void FoundData(int x)
    {
        data[x]=data[x<<1]+data[x<<1|1];
        sz[x]=sz[x<<1]+sz[x<<1|1];
    }
    void LazyDown(int x)
    {
        if(!f[x]) return ;
        f[x<<1]=f[x<<1|1]=1;
        data[x<<1]=data[x<<1|1]=sz[x<<1]=sz[x<<1|1]=0;
        f[x]=0;
    }
    void Updata(int x,int l,int r,int p,int d,int num)
    {
        data[x]+=d;sz[x]+=num;
        if(l==r) return ;
        int mid=(l+r)>>1;
        LazyDown(x);
        if(p<=mid) Updata(x<<1,l,mid,p,d,num);
        else Updata(x<<1|1,mid+1,r,p,d,num);
        FoundData(x);
    }
    void Sectiondin(int x)
    {
        data[x]=sz[x]=0;f[x]=1;
    }
    int SectionQuery(int x,int l,int r,int sum)
    {
        if(sum<=0) return 0;
        if(l==r) return data[x];
        int mid=(l+r)>>1,ans=0;
        LazyDown(x);
        if(sz[x<<1]<=sum)
        {
            ans+=data[x<<1];
            ans+=SectionQuery(x<<1|1,mid+1,r,sum-sz[x<<1]);
            return ans;
        }
        else return SectionQuery(x<<1,l,mid,sum);
    }
    void init(int x)
    {
        for(int i=0;i<bl[x].size();i++)
        {
            int col=bl[x][i],r=dr[x][i];
            if(!t[col]) Updata(1,1,m,r,1,0),t[col]=r;
            else if(t[col]>r)
            {
                Updata(1,1,m,t[col],-1,0);
                Updata(1,1,m,r,1,0);
                t[col]=r;
            }
            Updata(1,1,m,r,0,1);
        }
    }
    void dinit(int x)
    {
        Sectiondin(1);
        for(int i=0;i<bl[x].size();i++) t[bl[x][i]]=0;
    }
}zt;
void insert(int x,int y)
{
    for(int i=0;i<bl[y].size();i++)
    {
        bl[x].push_back(bl[y][i]);
        dr[x].push_back(dr[y][i]);
    }
    bl[y].clear();dr[y].clear();
}
void dfs1(int x,int fa)
{
    sz[x]=bl[x].size();
    for(int i=first[x];i;i=eage[i].nxt)
        if(eage[i].t!=fa)
        {
            dfs1(eage[i].t,x);
            sz[x]+=sz[eage[i].t];
            if(sz[son[x]]<sz[eage[i].t]) son[x]=eage[i].t;
        }
}
void dfs(int x,int fa)
{
    for(int i=first[x];i;i=eage[i].nxt)
        if(eage[i].t!=fa&&eage[i].t!=son[x])
        {
            dfs(eage[i].t,x);
            zt.dinit(eage[i].t);
        }
    if(son[x]) dfs(son[x],x);
    zt.init(x);
    for(int i=first[x];i;i=eage[i].nxt)
        if(eage[i].t!=fa&&eage[i].t!=son[x])
            zt.init(eage[i].t);
ans[x]=zt.SectionQuery(1,1,m,a[x]);
    if(son[x])
    {
        insert(son[x],x);
        swap(bl[son[x]],bl[x]);
        swap(dr[son[x]],dr[x]);
        for(int i=first[x];i;i=eage[i].nxt)
            if(eage[i].t!=fa)
                insert(x,eage[i].t);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        if(mp[y]==0) mp[y]=++cnt,y=cnt;
        else y=mp[y];
        bl[x].push_back(y);
        dr[x].push_back(i);
    }
    sz[0]=-1;
    dfs1(1,0);
    dfs(1,0);
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d",&x);
        printf("%d\n",ans[x]);
    }
    return 0;
}
ac

 

T3:

  說實話真的很水,三分鍾秒掉式子。大概說一下。

  設$dp[i][j]$為前$i$題最高難度為$j$的概率,$w[i]$為每種難度的勞累值。

  初始化:

    $dp[0][0]=1$

  轉移:

    $dp[i][j]=inv_m(\sum  \limits_{k=0}^j dp[i-1][k]+(j-1)dp[i-1][j])$

  解釋一下,我當前的最大難度是$j$的可能性有兩個:

  1.我之前某些點或者達到或者沒達到,但是在我這里都達到了,也就有了前面那個$\sum$

  2.我之前某些點達到了而我沒有達到,那就是我有$(j-1)$種情況,所以乘上$(j-1)$。

然后就切掉了。

 

下面說些心態的問題:

  我當時秒切T3覺得自己可厲害了可厲害了我心想這次穩了啊,爺要AK了啊,結果結果還是T1一調不出來心態就崩了,心想我怎么就調不出來。

  心態這個東西很微妙,你永遠不知道他怎么調整或者有什么影響。我之前能做到的是考前不對這次考試報任何希望,可是在答題過程中卻犯了這些禁忌,期望過高了,導致一但有什么波折就死心態。如果你是真的強三道題都全秒掉的話其實也沒啥問題,但是我這種一般人做不到全秒,而且喜歡自負的覺得自己能做到全秒。雖然真的基本都正解了,可是還是能力不足沒有拿到分數。

  那再立個$flag$下次要做到的是不在考前有任何期望,不再考試的時候有任何期望,心如止水。

  還有另外一個東西叫舍得。

  有舍才有得,考場上很多東西都要懂得取舍,不是文化課那兩下子,直接從頭做就行了的,可能丟失掉這一部分會換來更大的成績,這時候應當不再優柔寡斷,不要在僥幸的以為在過五分鍾你就能調出來,事實上到考試結束你也調不出來。舍得出去才能有得到,這是毋庸置疑的,考場上就那么多時間,拿到做多得分是最重要的,而不是去作出一道你耗費了大量心血或者一眼正解的題,沒有意義,這是考試不是刷題,刷題刷一天也沒人管你,但考試就三個半鍾頭,考的出來是他,考不出來也是他了。

  但是有時候並非有舍一定會有得,可能舍棄的是一個重要的作出某道題機會。但是考場時間非常緊迫,不管對錯的選擇,都沒有時間回頭想。

  為自己的選擇決定,決定了就去做,為決定負責,即使即將要為他后悔,在所不辭。

  什么都無法舍棄的人什么也無法改變。

  想起來之前看到的一句話,雖然沒什么關系,但至少教會你負責任。

  

  你是個小人物,一生難得做一件大事,這個機會很寶貴,要好好珍惜。你可以偶爾發個瘋,死一個人不要緊,自己死了也不要緊,可是有些事不能逃避。樹要開花,人要長大。       

                                       ——江洋

 

以上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM