2017.9总结

2017.9总结

9.14总结

​ 今天就比较gg。如果我没有记错的话,我已经有一段时间没有考上过150了。虽然说我这次考了192,但是(是个人都懂)这个成绩很烂。

​ 今天这道题比较简单,比一般的比赛简单(要不然我这种juruo是不可能上100的)。第一题是一道暴力dp,第二题是道大模拟,第三个目测是dp,但本juruo不会做。

第一题还是很套路的。一看就知道是个二位状态,然后我们枚举最后一次所选的凳子, fij 为我们选了i个凳子,最后一次选的第j个凳子的最后方案,那么我们很容易就得到状态转移方程式 fij=maxfijfi1s+sum ,因为每个凳子只能选一次,所以得保证 s<j 即可,然后找到 f[k][i](1im) 的最大值就好了。

​ 第二题就更加简单。这道题就是一个分数之间的加法,(可能跟数据水有关系)开个long long就够了,但是切记求lcm的时候先除以最大公约数,然后再乘分母,要不然会爆。其他的按照题意模拟既可。

​ 第三题乍一看是到dp(但它应该就是一道dp),然后想了想没有想出来,于是打算打个大暴力,但是由于我花在前两题的时间过多,于是第三题的暴力没有打完,于是暴0了。

​ 总体的总结一下,我觉得我的时间分配可能还是有一些问题,比赛刚开始应该把题全都看一遍(比如这次t2就比t1简单了一节);其次,我觉得我本场的最大的失误(灾难性失误)就是t2忘了判断分子为0如何输出的问题了,导致我这道题只拿了92分。这种失误也表现出了我的代码能力偏弱以及思维逻辑不够严谨等特点,所以我还是不能小看模拟题,适当的也要做一做复杂的模拟题。

9.21总结

比赛网址:http://zybuluo.com/Falsyta/note/772691

(貌似只有我心情好才写总结)

​ 今天的题其实我看着觉得很难,其实它就是很难。。。

​ t1就是求

(i=1m  n  mod  i)  mod  109+7

​ 看似很智障,其实就是很智障。

​ 这道题就是将 n  mod  i 写成 nni ×i

​ 这样我们就可以枚举一下 ni  的值的情况。它一共会有 m 种不同的值,然后显然这道题就做完了。

​ 下面我们看一下t2。

​ 这道题肯定就是选 n2+1 个数嘛,这样才能使两个总和尽量大。

​ 因为我们需要使两个总和都尽量大,这时我莫名其妙的想起了国王的游戏(瞎想),然后果断的取了乘积前k大的( k=n2+1 ),然后顺带就莫名其妙的A了。。。虽说我现在都不知道这个为什么是对的。

9.23模拟赛总结

比赛网址:https://zybuluo.com/Falsyta/note/894732

​ 今天这套题和21号的是一套题,不过比21号的难了太多了。。。难到随时想弃疗

​ 于是t1我就瞎打了个爆搜(深搜),然后顺理成章的拿了50分。

​ t2读了半天题,一直没有明白 3  s 是什么鬼。然后恍然大悟,然后就没有然后了。明显是一道AC自动机,然后我并不会写,所以之后我还是需要看一下AC自动机的相关博客,稍微学习一下。

​ t3听别人都说是智障题,当然结果反映它就是很智障。其实我也觉得很智障,不过我开始做这道题的时候只剩下了10min,于是我不动脑子瞎搞了一个看起来很对的拓扑排序的算法,于是乎它挂掉了,与此同时我发现了它是一道弱智的树形dp,可是为时已晚,就这样gg了。

​ 最终只是拿到了50分。。。

​ 下面我大概论述一下标算(我调出来的):

​ t1其实就是一个爆搜,不过我们需要使用bfs,这个其实没什么好说的啊,直接搞就完了,肯定是要比dfs快的啊(也不知道当时我的脑子是怎么瓦特的)!

​ t2就比较难,我并不会写,但是大概意思我是明白的滴。它是通过二进制建了 logm 个AC自动机,然后找size两桶的两个AC自动机合并,然后就没然后了。。。

​ t3就是树形dp,分别用两个数组 f g记录一些东西。 fi 表示以 i 为根的子树需要有多少条边反向过来。gi表示以 i 为都城最少需要反向多少条边。然后O(n)DP一下应该就可以了。

9.23 ACM北京赛区网络赛总结

​ 今天的ACM可是说是比上周的整体都要简单(其实也未必,上周都只做出来两道,今天也只做出来了两道,不过今天有一题有了正确的思路,就是没有时间继续往下想了)。

​ 今天的A题十分的水,一看就是签到题。

​ 显然,A题它就是一个大的模拟,没什么好说的,代码:

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1015;

int p[MAXN];
int ans = 2e9 + 15, ans1, ans2;
bool vis[MAXN];

inline int read(){
    int r = 0, z = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') z = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){r = r * 10 + ch - '0'; ch = getchar();}
    return r * z;
}

void pd(int minn, int mins, int x, int y){
    if((minn + mins) < ans){
        ans = minn + mins;
        ans1 = min(x, y);
        ans2 = max(x, y);
    }
}

void init(){
    int n, m;
    while(scanf("%d %d", &n, &m) != EOF){
        ans = 2e9 + 15;
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < n; i ++) p[i] = read();
        int q = read(), t;
        for(int i = 0; i < q; i ++){t = read(); vis[t] = 1;}
        for(int i = 0; i < n; i ++){
            int tmp = 1, minn = 1e9 + 7, x = i, y;
            if(vis[i]) continue;
            for(int j = i + 1; j < n; j ++){
                if(!vis[j]){
                    tmp ++;
                    if(p[j] < minn){
                        minn = p[j];
                        y = j;
                    }
                }
                if(tmp == m){pd(minn, p[x], x, y); break;}
            }
        }
        printf("%d %d\n", ans1, ans2);
    }
}

int main(){
    init();
    return 0;
}

​ I题一看就知道是线段树,不过我们需要求出最大值和最小值,改动仅此而已(最开始我没看到可以重复,于是还算了次小和最小,于是搞得很乱)不过最终我们还是成功的做出来了这道题,不过这也耗尽了我们队员我的脑细胞。

​ 接来下我们一直在搞G题,可是绞尽脑汁还是没有找到规律,可见我的智商低下啊。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef double DB;

const ll MAXN = 2 << 17 + 1;
const ll INF = 2 << 31;

struct Node{
    ll maxx, maxs, minn, mins;
    void init(){
        maxs = maxx = -INF;
        minn = mins = INF;
    }
}s[MAXN];

ll a[MAXN];

inline ll Max(ll a, ll b){return a > b ? a : b;}
inline ll Min(ll a, ll b){return a < b ? a : b;}

void build(int p, int l, int r){
    if(l == r){s[p].maxs = s[p].maxx = s[p].minn = s[p].mins = a[l]; return ;}
    int mid = (l + r) >> 1;
    build(p * 2, l, mid); 
    build(p * 2 + 1, mid + 1, r);
    int ls = p * 2, rs = p * 2 + 1;
    if(s[ls].maxx > s[rs].maxx){
        s[p].maxx = s[ls].maxx; s[p].maxs = s[rs].maxx;
    }
    else {
        s[p].maxx = s[rs].maxx; s[p].maxs = s[ls].maxx;
    }
    if(s[ls].minn < s[rs].minn){
        s[p].minn = s[ls].minn; s[p].mins = s[rs].minn;
    }
    else {
        s[p].minn = s[rs].minn; s[p].mins = s[ls].minn;
    }
}

inline int read(){
    ll r = 0, z = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') z = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){r = r * 10 + ch - '0'; ch = getchar();}
    return r * z;
}

void modify(int p, int l, int r, int x, int v){
    if(l == r){s[p].maxs = s[p].maxx = s[p].minn = s[p].mins = v; return ;}
    int mid = (l + r) >> 1;
    if(x <= mid) modify(p * 2, l, mid, x, v);
    else modify(p * 2 + 1, mid + 1, r, x, v);
    int ls = p * 2, rs = p * 2 + 1;
    if(s[ls].maxx > s[rs].maxx){
        s[p].maxx = s[ls].maxx; s[p].maxs = s[rs].maxx;
    }
    else {
        s[p].maxx = s[rs].maxx; s[p].maxs = s[ls].maxx;
    }
    if(s[ls].minn < s[rs].minn){
        s[p].minn = s[ls].minn; s[p].mins = s[rs].minn;
    }
    else {
        s[p].minn = s[rs].minn; s[p].mins = s[ls].minn;
    }
}

Node query(int p, int l, int r, int x, int y){
    Node ll, rr, res;
    ll.init(); rr.init(); res.init();
    if(x <= l && r <= y) return s[p];
    int mid = (l + r) >> 1;
    if(x <= mid) ll = query(p * 2, l, mid, x, y);
    if(y > mid) rr = query(p * 2 + 1, mid + 1, r, x, y);
    if(ll.maxx == -INF){
        res.maxx = rr.maxx; res.maxs = rr.maxs; res.minn = rr.minn; res.mins = rr.mins;
    }
    else if(rr.maxx == -INF){
        res.maxx = ll.maxx; res.maxs = ll.maxs; res.minn = ll.minn; res.mins = ll.mins;
    }
    else {
        if(ll.maxx > rr.maxx){
            res.maxx = ll.maxx; res.maxs = rr.maxx;
        }
        else {
            res.maxx = rr.maxx; res.maxs = ll.maxx;
        }
        if(ll.minn < rr.minn){
            res.minn = ll.minn; res.mins = rr.minn;
        }
        else {
            res.minn = rr.minn; res.mins = ll.minn;
        }
    }
    return res;
}

void init(){
    int T = read();
    while(T --){
        memset(a, 0, sizeof(a));
        ll n = read();
        n = (1 << n);
        for(int i = 1; i <= 4 * n; i ++) s[i].init();
        for(int i = 1; i <= n; i ++) a[i] = read();
        build(1, 1, n);
        /*
        for(int i = 1; i < 4 * n ; i ++){
            cout<<i<<": "<<endl;
            cout<<s[i].maxx<<" "<<s[i].maxs<<" "<<s[i].mins<<" "<<s[i].minn<<endl;
        }
        */
        int q = read();
        for(int i = 1; i <= q; i ++){
            int e = read();
            if(e == 1){
                int x = read() + 1, y = read() + 1;
                Node ans = query(1, 1, n, x, y);
                //cout<<ans.maxs<<" "<<ans.maxx<<" "<<ans.minn<<" "<<ans.mins<<endl;
                ll a1 = 1ll * ans.maxx * ans.maxs;
                ll a2 = 1ll * ans.mins * ans.minn;
                ll a3 = 1ll * ans.maxx * ans.minn;
                ll a4 = 1ll * ans.maxs * ans.mins;
                ll a5 = 1ll * ans.maxx * ans.mins;
                ll a6 = 1ll * ans.maxs * ans.minn;
                ll a7 = 1ll * ans.maxx * ans.maxx;
                ll a8 = 1ll * ans.maxs * ans.maxs;
                ll a9 = 1ll * ans.minn * ans.minn;
                ll a10 = 1ll * ans.mins * ans.mins;
                //if(ans.maxx == -INF){a1 = a3 = a4 = INF;}
                //if(ans.minn == INF){a2 = a3 = a4 = INF;}
                printf("%lld\n", Min(a1, Min(a2, Min(a3, Min(a4, Min(a5, Min(a6, Min(a7, Min(a8, Min(a9, a10))))))))));

            }
            else if(e == 2){
                int x = read() + 1, y = read();
                modify(1, 1, n, x, y);
            }
        }
    }
}
int main(){
    //fre();
    init();
    return 0;
}

/*

2
3
1 1 2 2 1 1 2 2
5
1 0 7
1 1 2
2 1 2
2 2 2
1 1 2
3
1 1 2 2 1 1 2 2
5
1 0 7
1 1 2
2 1 2
2 2 2
1 1 2

1
4
1 6 3 7 -4 6 4 -6 3 6 6 -4 6 -8 4 6
6
1 0 15
2 5 7
1 4 7
2 7 4
2 12 1
1 2 14

*/

​ 不过比赛结束后通过神犇的cjr的讲解终于是知道了规律是怎么找出来的了。

​ 其实这道题的规律是吧边界上的点与图的中间部分的点分开算, n m都先减一,然后我们先求 d=gcd(n,m) ,接着 n=nd m=md , 于是乎我们可以 用 ans 来表示答案, ans=n+m+(d1)×n×m 这样就算出答案了。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

inline int read(){
    int r = 0, z = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') z = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){r = r * 10 + ch - '0'; ch = getchar();}
    return r * z;
}

LL gcd(LL a, LL b){return !b ? a : gcd(b, a % b);}

void init(){
    LL n, m;
    LL ans;
    while(scanf("%lld %lld", &n, &m) != EOF){
        ans = 0;
        n --; m --;
        LL d = gcd(n, m);
        LL gg1 = n / d, gg2 = m / d;
        ans = gg1 + gg2 + (d - 1) * gg1 * gg2;
        printf("%lld\n", ans);
    }
}

int main(){
    init();
    return 0;
}

​ 总的来说,今天的ACM我们已经尽力了,可能实力差距确实很大,所以我还是需要多加练习啊!

9.24模拟赛总结

今日题目链接:https://zybuluo.com/stevenzheng2002/note/895717

​ 10分。。。

​ 尴尬的10分,居然t1的40分暴力都打错了,真的是。。。无语了。

​ 据说这套题很难(貌似并不是据说,就是很难),还有国家集训队的作业,所以考不高也很正常,但是暴力都没打过就有些说不过去了啊!

9.24 ACM南宁赛区网络赛总结

​ 这个。。。

​ 今天出了些小偏差,貌似北京交通大学在跟我们共用一个号。。。然后我们就被别人带着飞了。。。每次刚看完题,那边就把这道题A了,十分interesting,这样导致我们自己A的题目数量只有2道(他们做太快了,若果慢的话,我们也能A)。

​ 总体来说,今天的ACM没有像前两天那样特别智障的签到题,但是中等偏易的题比较多,得有个7道左右,所以今天排在400多都要A个8,9道,竞争十分激烈。

​ 最后我们还是需要调一下这些题,毕竟好多不是自己A的(虽然会写)。

9.26总结

​ 今天这个生日过得十分糟糕。。。本以为今天这套简单题能让我上200,没想到。。。t1就写挂了。

​ 今天的题相较过去一段时间的题来说,简单多了不少,听其他人说只有t2的10%难拿,其他的都是水题。然而写了2h t2的我表示t3一眼都没看。。。

​ 先说一下今天的题。t1确实很水,就是枚举你需要用多少辆车就行了,先把重量从大到小排个序,对于用 x 辆车,直接用深搜(爆搜)来检验是否合理即可。千万不要忘了剪枝!!!我因为没有剪枝挂了4个点。。。剪枝大概就是先求一个重量总和sum,然后车辆数从 sum÷ w 开始算到n即可!

​ t2其实也不是特别难,主要是10分的C类型比较难拿。颂芬数据直接跑一遍SPFA即可。30%的A类数据是裸的LCA,不多赘述;50%的B类数据就是环套树,判断一下选不选此边即可。

​ 总的来讲,我的思维训练的还是不到位。t2能写出2h。。。而且做题前一定要计算一下复杂度,看看是不是差不多能过。然后还有就是读题一定要读清楚!!!读不清楚就多读两遍!!!比如我今天t2的B类数据我就理解成 n 个点组成一个大环了。。。

9.29总结

​ 今天主要就做了LCA和dijsktra方面的题,共6道。感觉我调了很多“灵异”方面的问题。比如cout,printf输出的答案。

​ 其实说是六道,一共也就相当于做了2道,因为有4道题都是模板题。我大概就说一下小z摘玉米和货车运输吧。

​ 小z摘玉米就是一道比较弱的题。题意大概是就说一棵树,q次询问,每次询问 u v,求 u v的路径上的所有点的最大值与次大值之和(包括 u v)。

​ 这道题其实几乎就是裸的LCA。只不过我们需要加两个数组 hx hn hx[i][j] 表示的是在 i i 2j 倍的祖先的所有点的点权的最大值(不包括 i 2j倍祖先),预处理也就不用我说了,然后这要就是在求lca的过程中随着x和y的往上更新,也顺便更新一下目前的最大值与次大值。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef double DB;

int Max1(int a, int b, int c, int g){
    int h[6];
    h[1] = a, h[2] = b, h[3] = c, h[4] = g;
    sort(h + 1, h + 5);
    return h[4];
}

int Max2(int a, int b, int c, int g){
    int h[6];
    h[1] = a, h[2] = b, h[3] = c, h[4] = g;
    sort(h + 1, h + 5);
    return h[3];
}

const int MAXN = 1e5 + 15;

struct Node{
    int to, nxt;
}g[MAXN * 2];

int ans1 = -1, ans2 = -1;
int cnt = 0, n;
int a[MAXN], d[MAXN];
int head[MAXN], p[MAXN][20];
int hx[MAXN][20], hn[MAXN][20];

void add(int u, int v){
    g[++ cnt] = (Node){v, head[u]};
    head[u] = cnt;
    g[++ cnt] = (Node){u, head[v]};
    head[v] = cnt;
}

int read(){
    int r = 0, z = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') z = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){r = r * 10 + ch - '0'; ch = getchar();}
    return r * z;
}

void init(){
    memset(d, -1, sizeof(d));
    for(int i = 1; i <= n; i ++) hx[i][0] = a[i];
    d[1] = 0;
}

void dfs(int u){
    for(int i = head[u]; i; i = g[i].nxt){
        int v = g[i].to;
        if(d[v] == -1){
            d[v] = d[u] + 1;
            p[v][0] = u;
            dfs(v);
        }
    }
}

void pre(){
    for(int i = 1; (1 << i) <= n; i ++){
        for(int j = 1; j <= n; j ++){
            if(p[j][i - 1]){
                p[j][i] = p[p[j][i - 1]][i - 1];
                hx[j][i] = max(hx[j][i - 1], hx[p[j][i - 1]][i - 1]);
                hn[j][i] = Max2(hx[j][i - 1], hx[p[j][i - 1]][i - 1], hn[j][i - 1], hn[p[j][i - 1]][i - 1]);
            }
        }
    }
}

int lca(int x, int y){
    if(d[x] < d[y]) swap(x, y);
    int i;
    for(i = 0; (1 << i) <= n; i ++);
    i --;
    for(int j = i; j >= 0; j --)
        if(d[x] - (1 << j) >= d[y]){
            ans1 = max(hx[x][j], ans1);
            ans2 = max(hn[x][j], ans2);
            x = p[x][j];
        }

    if(x == y) return x;
    for(int j = i; j >= 0; j --){
        //cout<<x<<endl;
        if(p[x][j] != p[y][j]){
            int tmp2 = Max2(hx[x][j], hn[x][j], hx[y][j], hn[y][j]);
            int tmp1 = Max1(hx[x][j], hn[x][j], hx[y][j], hn[y][j]);
            int gg2 = Max2(ans1, ans2, tmp1, tmp2);
            int gg1 = Max1(ans1, ans2, tmp1, tmp2);
            ans1 = gg1, ans2 = gg2;
            x = p[x][j];
            y = p[y][j];
        }
    }
    int tmp2 = Max2(hx[x][0], hn[x][0], hx[y][0], hn[y][0]);
    int tmp1 = Max1(hx[x][0], hn[x][0], hx[y][0], hn[y][0]);
    int gg2 = Max2(ans1, ans2, tmp1, tmp2);
    int gg1 = Max1(ans1, ans2, tmp1, tmp2);
    ans1 = gg1, ans2 = gg2;
    return p[x][0];
}

void work(){
    n = read();
    for(int i = 1; i <= n; i ++) a[i] = read();
    for(int i = 1; i < n; i ++){
        int u = read(), v = read();
        add(u, v);
    }
    init();
    dfs(1);
    pre();
    /*
    for(int i = 1; i <= n; i ++){
        for(int j = 0; (1 << j) <= n; j ++) printf("%d ", hn[i][j]);
        printf("\n");
    }
    */
    int Q = read();
    while(Q --){
        ans1 = 0, ans2 = 0;
        int u = read(), v = read();
        int gr = lca(u, v);
        //cout<<ans1<<" "<<ans2<<endl;
        if(a[gr] >= ans1){
            ans2 = ans1;
            ans1 = a[gr];
        }
        else if(a[gr] >= ans2) ans2 = a[gr];
        printf("%d\n", ans1 + ans2);
    }
}

int main(){
    work();
    return  0;
}

货车运输:

​ 这道题说的大概就是一棵树, q 次询问,每次询问是u v ,求u v 的路径上的边权最小值。

​ 这道题相对来讲比上一道题还简单,然而我却出了一些灵异事件,比如cout和printf输出的答案不太一样,结果花了我5.5h找到了错误:for里面的i我重复定义了。。。这tm就尴尬了。

​ 这道题主要是在LCA模板上加一个 h 数组,h[i][j]表示点 i i 2j 倍祖先的路上的所有边的边权最小值。然后同上面一道题一样,在求lca的时候更新当前的 ans 。代码如下:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef double DB;

LL Max(LL a, LL b){return a > b ? a : b;}
LL Min(LL a, LL b){return a < b ? a : b;}

const int MAXN = 1e5 + 15;

struct Node{
    int from, to, dis;
}e[MAXN];

struct Edge{
    int to, nxt, dis;
}g[MAXN];

int n, m;
int cnt_edge = 0, ans;
int fa[MAXN / 10];
int head[MAXN / 10], cnt = 0;
int p[MAXN / 10][20], h[MAXN / 10][20], d[MAXN/ 10];
bool flag[MAXN / 10];

void add(int u, int v, int dis){
    e[++ cnt_edge].from = u;
    e[cnt_edge].to = v;
    e[cnt_edge].dis = dis;
}

void add_edge(int u, int v, int dis){
    g[++ cnt].to = v;
    g[cnt].nxt = head[u];
    g[cnt].dis = dis;
    head[u] = cnt;
}

int read(){
    int r = 0, z = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') z = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){r = r * 10 + ch - '0'; ch = getchar();}
    return r * z;
}

void fre(){
    freopen(".in", "r", stdin);
    freopen(".out", "w", stdout);
}

int cmp(Node x, Node y) {return x.dis > y.dis;}

int getfa(int x){
    if(x == fa[x]) return fa[x];
    return fa[x] = getfa(fa[x]);
}

void kruskal(){
    sort(e + 1, e + m + 1, cmp);
    for(int i = 1; i <= n; i ++) fa[i] = i;
    int k = 0;
    for(int i = 1; i <= m; i ++){
        int u = e[i].from, v = e[i].to, dis = e[i].dis;
        int f1 = getfa(u), f2 = getfa(v);
        if(f1 != f2){
            fa[f2] = f1;
            add_edge(u, v, dis);
            add_edge(v, u, dis); 
            k ++;
        }
        if(k == n - 1) break;
    }
}

void fuckit(){
    memset(d, -1, sizeof(d));
    for(int i = 1; i <= n; i ++){
        for(int j = 0; (1 << j) <= n; j ++) h[i][j] = 2e9;
    }
    d[1] = 0;
}

void dfs(int u){
    for(int i = head[u]; i; i = g[i].nxt){
        int v = g[i].to;
        if(d[v] == -1){
            d[v] = d[u] + 1;
            p[v][0] = u;
            h[v][0] = g[i].dis;
            flag[v] = 1;
            dfs(v);
        }
    }
}

void work(){
    for(int i = 0; (1 << i) <= n; i ++){
        for(int j = 1; j <= n; j ++){
            if(p[j][i - 1]){
                p[j][i] = p[p[j][i - 1]][i - 1];
                h[j][i] = min(h[j][i - 1], h[p[j][i - 1]][i - 1]);
            }
        }
    }
}

int lca(int x, int y){
    int i;
    ans = 2e9;
    if(d[x] < d[y]) swap(x, y);
    for(i = 0; (1 << i) <= d[x]; i ++);
    i --;
    for(int j = i; j >= 0; j --){
        if(d[x] - (1 << j) >= d[y]){ans = min(ans, h[x][j]); x = p[x][j];}
    }
    //cout<<x<<"*cout"<<y<<endl;
    //printf("%d %d\n", x, y);
    if(x == y) return x;
    for(int j = i; j >= 0; j --){
        if(p[x][j] != p[y][j] && p[x][j]){
            ans = min(ans, h[x][j]);
            x = p[x][j];
            ans = min(ans, h[y][j]);
            y = p[y][j];
        }
    }
    return p[x][0];
}

int cz(int u, int k){
    int i, res = 2e9 + 7;
    for(i = 0; (1 << i) <= k; i ++);
    i --;
    for(; i >= 0; i --)
        if(k & (1 << i)){
        res = min(res, h[u][i]);
        u = p[u][i];
        k -= (1 << i); 
    }
    return res;
}

void init(){
    n = read(), m = read();
    for(int i = 1; i <= m; i ++){
        int u = read(), v = read(), dis = read();
        add(u, v, dis);
    }
    kruskal();
    fuckit();
    for(int i = 1; i <= n; i ++){
        if(!flag[i]){flag[i] = 1; dfs(i);}
    }
    work();
    int q = read();
    /*
    for(int i = 1; i <= n; i ++) cout<<d[i]<<" ";
    cout<<endl;

    for(int i = 1; i <= n; i ++){
        for(int j = 0; (1 << j) <= n; j ++) cout<<h[i][j]<<" ";
        cout<<endl;
    }
    for(int i = 1; i <= n; i ++) printf("%d ", fa[i]);
    printf("\n");
    */
    while(q --){
        int a = read(), b = read();
        if(getfa(a) != getfa(b)) printf("-1\n");
        else {
            int tmp = lca(a, b);
            //printf("%d\n", tmp);
            printf("%d\n",  min(cz(a, d[a] - d[tmp]), cz(b, d[b] - d[tmp])));
        }
    }
}

int main(){
    //fre();
    init();
    return  0;
}

九月份整体总结

​ 这个月貌似天天都在练,好像没有歇过。。。这个月我已经比较累了,所以十一放假我请了三天假(貌似放假也不能放松啊)。这个九月份做了好多好多套模拟赛,大概一周4套,所以可能做了15套左右,加上这个月还有ACM,所以。。。身体已经经受不住了啊。。。不过看看小学弟还有dalao们还在拼命地练习,这让我感到十分羞愧,毕竟我跟dalao们还有很大的差距啊!!!

​ 纵观整个九月份,我的模拟考成绩不算理想,虽说每套的题都比noip提高组略难。其实看看题解,我感觉我欠缺的方面确实还有很多。

​ 1.知识广度不够,即会的知识过少。比如什么高端的树链剖分啊,高级的暴力啊,还有各种数论知识我都不会(尴尬),于是我只能在这短暂的一个半月时间里狂学。唉,差的确实太多了。还有80多天,要加油了!

​ 2.知识深度不够。这正跟jls所说的模块方面的欠缺有关。其实我刷题刷的很少,导致我会某个知识点,但是真到比赛的时候,需要有一些变动,添加之类的我就不会了,这跟刷题少有着千丝万缕的联系,所以在接下来的这一个月,不仅要多学一些知识,更重要的是要多做题,要不然真到11.11的时候就gg了。。。

​ 3.数学太差。这个。。。感觉一时间也不太好补,这方面的欠缺主要体现在找规律找不出来,数学题中的推导不会推之类的问题。像lzy这种随随便便参加数学竞赛都能拿个省一的人来说做信息中的数学题就是小菜一碟。虽说我的智商发展限制了我到达他那么厉害的程度,但是我仍然需要在这方面要有很大的提高,要不然考试也会吃很多亏的。

​ 好了,说完了我在这一个月所发现的不足之处之后,我貌似好像就没什么优点了。。。好吧,我承认了我是一个什么都不会,什么都不行的,智商为 的蒟蒻(也许我还没有达到一个做为人的基本标准。。。)

​ 不管怎样,就算菜到不可救药,我还是要努力啊,要不然连省一都拿不到的话就太tm尴尬了。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值