「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$下次要做到的是不在考前有任何期望,不再考试的时候有任何期望,心如止水。

  还有另外一个东西叫舍得。

  有舍才有得,考场上很多东西都要懂得取舍,不是文化课那两下子,直接从头做就行了的,可能丢失掉这一部分会换来更大的成绩,这时候应当不再优柔寡断,不要在侥幸的以为在过五分钟你就能调出来,事实上到考试结束你也调不出来。舍得出去才能有得到,这是毋庸置疑的,考场上就那么多时间,拿到做多得分是最重要的,而不是去作出一道你耗费了大量心血或者一眼正解的题,没有意义,这是考试不是刷题,刷题刷一天也没人管你,但考试就三个半钟头,考的出来是他,考不出来也是他了。

  但是有时候并非有舍一定会有得,可能舍弃的是一个重要的作出某道题机会。但是考场时间非常紧迫,不管对错的选择,都没有时间回头想。

  为自己的选择决定,决定了就去做,为决定负责,即使即将要为他后悔,在所不辞。

  什么都无法舍弃的人什么也无法改变。

  想起来之前看到的一句话,虽然没什么关系,但至少教会你负责任。

  

  你是个小人物,一生难得做一件大事,这个机会很宝贵,要好好珍惜。你可以偶尔发个疯,死一个人不要紧,自己死了也不要紧,可是有些事不能逃避。树要开花,人要长大。       

                                       ——江洋

 

以上。

转载于:https://www.cnblogs.com/Lrefrain/p/11267557.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值