A · F · O —— JLOI2018翻车记(附Day1简要题解)

JLOI2018翻车记

并不知道该怎么写... 算了仍是按照标准剧情来吧c++

这应该是一篇写得很是差的流水帐...优化

2018.04.04 Day -1

省选前在机房的最后一天。ui

压力并非很大,毕竟联赛 JL rank 1。spa

晚上动员,和同窗制定了策略:不管如何都不要挂题(flag)。c++11

2018.04.05 Day 0

清明。code

前一天晚上(其实应该是这一天早上)梦见了本身一试考挂... 后来就醒了... 颓了一上午。博客

下午母上回来,不颓不颓,开始更博客。string

后来因为各类缘由,最终只更了两篇... 感受效率好低...it

2018.04.06 Day 1

九省联考一试。io

早上来得不算晚,和同窗一块儿奶题,奶了一些都没出的东西...

开始抽签,抽到了10号,左边9号l1ll5,左前方8号JZYshuraK。

进了考场,到了8点,解压,稀里糊涂地开始看题。

Woc T1 什么鬼?看数据范围猜了个 $O(n^6)$ 的贪心。

Woc T2 什么鬼?贪心?老子确定能猜出来。

Woc T3 什么鬼?等等我好像会写 $O(n^3)$ 暴力... 那就够了。

推了下 T1 的大样例发现不对,感受必定不是裸贪心,因而想状压。把状态数打出来发现只有 18W 左右所以状压dp一下好像能过。写了个正着的dp发现WA了,想到前后手决策不一样,反过来推,过了大样例。

T2 猜了个直接贪心法,对拍了1000组发现WA了,原来是有重复数字的锅。想到 [HNOI2015]菜肴制做 ,正着推不行考虑反着推,即把小的数尽可能放到后面。又具体考虑了一下重复数字的状况,写了线段树,过了样例及20W组对拍。

T3 看到时间7s直接写了个 $O(n^3)$ 的暴力,简单测了一下 $n=1111$ 的状况发现开long long只需6s左右,使用unsigned int更是跑进了2s。因而卡卡了常,$n=1666$ 的链压到了4s如下。

此时距离考试结束还有1h+,检查各类 文件名/文件输入输出 直到考试结束。

出考场以为本身老稳了,尽管 T2 每一个人策略不同可能有点慌,然而我过了20W组对拍,不虚。

去日新楼一块儿吃饭,回来当作绩。

按照JL的尿性,成绩应该是按照分数从大到小排的。

为何我都AK了还找不到本身的名字啊...

后来终于在下面某位置找到了本身,rank 10,100/0/0...

考试以前说着千万不要挂题,可怎么仍是挂了啊...

回到本身的机器上一探究竟,测了大点发现不对,然而是diff的锅;测了小点,毫无悬念A了...

各类检查文件名之类的仍是没查出错误...

最后,我看到了-std=c++11...

想到了什么不应想到的事情... 我 T2 和 T3 全用的邻接表存边... 全使用了next[]...

本机编译了如下果真过不去...

我傻在那里。200分的差距,一落千丈。

一样被卡的还有CQzhangyu... 他 T2 没有用next[]所以还有20pts。

热闹是它们的,我什么也没有。

再后来,找了各类老师,各类体校学长,仍是没能把分数找回来... 填了一张申诉表,到如今(2018.04.12)好像还没发回来...

完了,全完了,凉了,翻车了。

难道我JL现役最强OIer就要省选退役了吗...

在家哭了一下午,心态却是好了一些:“老子今天300大家才210,看我明天随便翻盘” 。

然而晚上仍是睡不着觉,压力太大了,毕竟须要达成:超过LJ80pts/超过CKH70pts/超过CQ0pts 三者之二才能二试翻盘。折腾了半天终于睡着了。

2018.04.07 Day 2

吉林省选二试。

到了候考室压力仍是挺大... 强行装做乐观的样子,和其余人谈笑风生。

并不从新抽签,所以过了一下子就直接进考场了。

。。。

。。。

。。。

而后就没有而后了。

永远不要以为你能翻盘,由于你根本就不知道“盘”是什么样子的。

——GXZlegend

T1 裸矩乘,直接秒掉,没啥意义的题,全场切。

T2 显然dfs序前驱后继,直接秒掉,没啥意义的题,全场切。

T3 暴力36pts。

这他妈还考个P了?白送236pts?

另外你他妈前一天开C++11,今天不开?

出题人你是吃*的吗?

尽本身最大努力也没有想出来 T3 怎么作... 因而尽量优化了搜索的复杂度,最终 T3 拿了64pts。

出考场,好像没人挂题。只能期望别人文件名写错了吧。

最后看分,T2 全场卡一个点95pts,其它的和我想象的彻底一致。

CQzhangyu 切了 T3 ,然而被卡常了,进队无望。

后来知道JL换题了,气愤不已,然而已经没有什么用了。

至此,学了5年OI的JL队长GXZlegend,退役了。

和潘老师打了一下午球,晚上老师请吃饭,而后回机房颓了两个小时,庆祝退役的本身。


Day1简要题解

chess

状态数只有 $C_{n+m}^n<190000$ ,所以预处理状态以后从后往前dp,设 $f[i]$ 表示当前是 $i$ 状态,下一个取的人最多可以比对手高多少分。转移时枚举取哪个便可。

#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
map<ll , int> mp;
int n , m , a[12][12] , b[12][12] , v[12] , c[200010][12] , s[200010] , tot , f[200010];
ll bas[12] , val[200010];
void dfs(int x)
{
    int i;
    if(x > m)
    {
        tot ++ ;
        for(i = 1 ; i <= m ; i ++ ) c[tot][i] = v[i] , s[tot] += v[i] , val[tot] = val[tot] + v[i] * bas[i - 1];
        c[tot][0] = v[0] , mp[val[tot]] = tot;
        return;
    }
    for(i = 0 ; i <= v[x - 1] ; i ++ ) v[x] = i , dfs(x + 1);
}
int main()
{
    freopen("chess.in" , "r" , stdin);
    freopen("chess.out" , "w" , stdout);
    int i , j;
    scanf("%d%d" , &n , &m);
    bas[0] = 1;
    for(i = 1 ; i <= m ; i ++ ) bas[i] = bas[i - 1] * (n + 1);
    for(i = 1 ; i <= n ; i ++ ) for(j = 1 ; j <= m ; j ++ ) scanf("%d" , &a[i][j]);
    for(i = 1 ; i <= n ; i ++ ) for(j = 1 ; j <= m ; j ++ ) scanf("%d" , &b[i][j]);
    v[0] = n , dfs(1);
    memset(f , 0xc0 , sizeof(f)) , f[tot] = 0;
    for(i = tot - 1 ; i ; i -- )
    {
        for(j = 1 ; j <= m ; j ++ )
        {
            if(c[i][j] < c[i][j - 1])
            {
                if(s[i] & 1) f[i] = max(f[i] , b[c[i][j] + 1][j] - f[mp[val[i] + bas[j - 1]]]);
                else f[i] = max(f[i] , a[c[i][j] + 1][j] - f[mp[val[i] + bas[j - 1]]]);
            }
        }
    }
    printf("%d\n" , f[1]);
    return 0;
}

iiidx

从后往前贪心,尽可能把小的数放到后面,但这样处理重复的数可能会错误,所以对于出现 $cnt[i]$ 次的 $i$ ,从 $cnt[i]$ 到 $1$ 枚举放到后面的哪一个位置。使用线段树上二分解决。

#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 500010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
int a[N] , si[N] , head[N] , to[N] , next[N] , cnt , ans[N] , sum[N << 2];
inline void add(int x , int y)
{
    to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt , si[x] += si[y];
}
void update(int p , int a , int l , int r , int x)
{
    sum[x] += a;
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(p <= mid) update(p , a , lson);
    else update(p , a , rson);
}
int query(int k , int l , int r , int x)
{
    if(l == r) return l;
    int mid = (l + r) >> 1;
    if(sum[x << 1 | 1] < k) return query(k - sum[x << 1 | 1] , lson);
    else return query(k , rson);
}
int main()
{
    freopen("iiidx.in" , "r" , stdin);
    freopen("iiidx.out" , "w" , stdout);
    int n , i , last = 1 , j , l , t;
    double k;
    scanf("%d%lf" , &n , &k);
    for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , si[i] = 1;
    sort(a + 1 , a + n + 1);
    for(i = n ; i ; i -- ) add((int)floor(i / k) , i);
    for(i = head[0] ; i ; i = next[i]) update(to[i] , si[to[i]] , 1 , n , 1);
    for(i = 1 ; i <= n ; i = last)
    {
        while(last <= n && a[last] == a[i]) last ++ ;
        for(j = last - i ; j ; j -- )
        {
            t = query(j , 1 , n , 1) , ans[t] = a[i] , update(t , -si[t] , 1 , n , 1);
            for(l = head[t] ; l ; l = next[l]) update(to[l] , si[to[l]] , 1 , n , 1);
        }
    }
    for(i = 1 ; i <= n ; i ++ ) printf("%d " , ans[i]);
    return 0;
}

coat

枚举 $k$ 大值,单次 $O(n^2)$ 树形背包暴力,注意要用uint,卡卡常便可,没什么好说的。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1675
#define mod 64123
using namespace std;
typedef unsigned int ui;
int a[N] , id[N] , head[N] , to[N << 1] , next[N << 1] , cnt , si[N] , last[N] , now;
ui f[N][N];
bool cmp(int x , int y) {return a[x] == a[y] ? x <= y : a[x] < a[y];}
inline void add(int x , int y) {to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;}
void dfs(int x , int fa)
{
    int i , j , k;
    for(i = last[x] ; i <= si[x] ; i ++ ) f[x][i] = 0;
    if(cmp(id[now] , x)) si[x] = last[x] = 1;
    else si[x] = last[x] = 0;
    f[x][si[x]] = 1;
    for(i = head[x] ; i ; i = next[i])
    {
        if(to[i] != fa)
        {
            dfs(to[i] , x);
            for(j = si[x] ; j >= last[x] ; j -- )
                for(k = si[to[i]] ; k >= last[to[i]] ; k -- )
                    f[x][j + k] = (f[x][j + k] + f[x][j] * f[to[i]][k]) % mod;
            si[x] += si[to[i]];
        }
    }
    for(i = last[x] ; i <= si[x] ; i ++ ) f[0][i] = (f[0][i] + f[x][i]) % mod;
}
int main()
{
    freopen("coat.in" , "r" , stdin);
    freopen("coat.out" , "w" , stdout);
    int n , k , w , i , x , y;
    ui ans = 0;
    scanf("%d%d%d" , &n , &k , &w);
    for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , id[i] = i;
    for(i = 1 ; i < n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x);
    sort(id + 1 , id + n + 1 , cmp);
    for(now = 1 ; now <= n ; now ++ )
    {
        memset(f[0] , 0 , sizeof(f[0]));
        dfs(1 , 0);
        for(i = k ; i <= n ; i ++ )
            ans = (ans + f[0][i] * (a[id[now]] - a[id[now - 1]])) % mod;
    }
    printf("%u\n" , ans);
    return 0;
}
相关文章
相关标签/搜索