Solutions - 板刷 UOJ 小记

开始板刷 UOJ!

UOJ #1. A + B Problem

AC Time:2026-04-16 16:23:16

全 UOJ 最难题!(

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

int main(){
	int a, b;
	cin >> a >> b;
	cout << a+b;
	return 0;
}

UOJ #2. 【NOI2014】起床困难综合症

AC Time:2026-04-16 17:25:07

比较基础的题了。

发现每一位是独立的,我们先预处理出每一位选 \(0\)\(1\),运算以后最后的值。然后就可以用一种类似数位 DP 的方式搞了。

然后做完了。

复杂度:\(\mathrm O(n \log V)\)\(V\) 为值域。

UOJ #3. 【NOI2014】魔法森林

AC Time:2026-03-23 17:53:34

这题在我板刷 UOJ 之前就 A 了,为了完整性放在这里。

枚举 A 的最大值,维护在 A 的最大值取某个值的情况下 B 的 MST,发现是一个动态加边 MST,用 LCT 维护。

然后做完了。\(\mathrm O(n \log n)\)。实现的时候为了方便维护可以把边转换成点。

#include <bits/stdc++.h>
#define llong long long
#define N 200005
using namespace std;

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int n, m, ans = 1e9+7;
struct Edge{
    int u, v, w1, w2;
};
Edge G[N];

typedef pair<int, int> Node;
int son[N][4], fa[N], id[N], tag[N];
Node val[N];
int tmp[N], top;

#define get(x) (son[fa[x]][0] == x ? 0 : (son[fa[x]][1] == x ? 1 : 2))

inline void pushup(int x){
    val[x] = max({val[son[x][0]], val[son[x][1]], make_pair(G[id[x]].w2, id[x])});
    return;
}
inline void addtag(int x){
    swap(son[x][0], son[x][1]);
    tag[x] ^= 1;
    return;
}
inline void pushdown(int x){
    if(!tag[x]) return;
    addtag(son[x][0]), addtag(son[x][1]);
    tag[x] = 0;
    return;
}
inline void rotate(int y){
    int x = fa[y], k = get(y);
    son[fa[x]][get(x)] = y, fa[y] = fa[x];
    son[x][k] = son[y][k^1], fa[son[y][k^1]] = x;
    son[y][k^1] = x, fa[x] = y;
    pushup(x), pushup(y);
    return;
}
inline void splay(int x){
    int now = x;
    tmp[top = 1] = now;
    while(get(now) != 2) tmp[++top] = now = fa[now];
    while(top) pushdown(tmp[top--]);
    while(get(x) != 2){
        if(get(fa[x]) != 2)
            rotate(get(x) == get(fa[x]) ? fa[x] : x);
        rotate(x);
    }
    return;
}

inline void access(int x){
    for(int y = 0; x; x = fa[y = x])
        splay(x), son[x][1] = y, pushup(x);
    return;
}
inline void makeroot(int x){
    access(x);
    splay(x);
    addtag(x);
    return;
}
inline int find(int x){
    access(x);
    splay(x);
    pushdown(x);
    while(son[x][0]) pushdown(x = son[x][0]);
    splay(x);
    return x;
}
inline void split(int x, int y){
    makeroot(x);
    access(y);
    splay(y);
}
inline void link(int x, int y){
    access(x);
    makeroot(x);
    splay(x);
    fa[x] = y;
    return;
}
inline void cut(int x, int y){
    makeroot(x);
    access(y);
    splay(y);
    son[y][0] = fa[x] = 0;
    pushup(y);
    return;
}

int main(){
    read(n, m);
    for(int i = 1; i <= m; ++i)
        read(G[i].u, G[i].v, G[i].w1, G[i].w2);
    sort(G+1, G+m+1, [&](Edge o1, Edge o2){return o1.w1 < o2.w1;});
    for(int i = 1; i <= m; ++i)
        id[i+n] = i, val[i+n] = make_pair(G[i].w2, i);
    for(int i = 1; i <= m; ++i){
        int u = G[i].u, v = G[i].v;
        if(find(u) != find(v)){
            link(u, i+n);
            link(v, i+n);
        }
        else{
            split(u, v);
            splay(u);
            if(val[u].first > G[i].w2){
                int j = val[u].second;
                cut(G[j].u, j+n);
                cut(G[j].v, j+n);
                link(u, i+n);
                link(v, i+n);
            }
        }
        if(find(1) == find(n)){
            split(1, n);
            splay(1);
            ans = min(ans, G[i].w1+val[1].first);
        }
    }
    if(ans > 1e9) puts("-1");
    else printf("%d", ans);
    return 0;
}

UOJ #4. 【NOI2014】消除游戏

提交答案题不想做。

UOJ #5. 【NOI2014】动物园

AC Time:2026-04-16 21:06:11

发现题目要求每个点在 fail 树上最大的不大于 \(\lfloor \frac i 2 \rfloor\) 的祖先,于是倍增跳祖先即可。

#include <bits/stdc++.h>
#define llong long long
#define N 1000006
using namespace std;

constexpr llong p = 1000000007;

char a[N];
int nxt[N], dep[N], to[N][21];
int n; llong res = 1;

void _init(){
    res = 1;
}

int _main(){
    scanf("%s", a+1);
    n = strlen(a+1);
    dep[1] = 1;
    for(int i = 2; i <= n; ++i){
        nxt[i] = nxt[i-1];
        while(nxt[i] && a[nxt[i]+1] != a[i]) nxt[i] = nxt[nxt[i]];
        if(a[nxt[i]+1] == a[i]) ++nxt[i];
        dep[i] = dep[nxt[i]]+1;
    }
    for(int i = 1; i <= n; ++i) to[i][0] = nxt[i];
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= 20; ++j)
            to[i][j] = to[to[i][j-1]][j-1];
    for(int i = 1; i <= n; ++i){
        int now = i;
        for(int j = 20; ~j; --j)
            if(to[now][j] > i/2) now = to[now][j];
        now = to[now][0];
        res = res*(dep[now]+1)%p;
    }
    printf("%lld\n", res);
    return 0;
}

int T;
int main(){
    scanf("%d", &T);
    while(T--) _init(), _main();
    return 0;
}

UOJ #6. 【NOI2014】随机数生成器

AC Time:2026-04-17 19:35:27

发现肯定会选当前可选范围内最小的数,于是直接模拟即可。

记得卡空间。

#include <bits/stdc++.h>
#define llong long long
#define N 5005
using namespace std;

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int a2[N*N];
int n, m, q, a, b, c, d;
llong x;

short b1[N*N], b2[N*N];
int ans[N*2];
bitset<N> vis[N];

int main(){
    read(x, a, b, c, d);
    read(n, m, q);
    for(int i = 1; i <= n*m; ++i) a2[i] = i;
    for(int i = 1; i <= n*m; ++i){
        x = (a*x%d*x%d+b*x%d+c)%d;
        swap(a2[i], a2[x%i+1]);
    }
    while(q--){
        int x, y; read(x, y);
        swap(a2[x], a2[y]);
    }
    for(int i = 1, k = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j, ++k)
            b1[a2[k]] = i, b2[a2[k]] = j;
    for(int i = 0; i <= n+1; ++i) vis[i][0] = vis[i][m+1] = true;
    for(int i = 0; i <= m+1; ++i) vis[0][i] = vis[n+1][i] = true;
    for(int i = 1, j = 0; i <= n*m && j <= n+m-1; ++i){
        if(vis[b1[i]][b2[i]]) continue;
        int x = b1[i], y = b2[i];
        ans[++j] = a2[(x-1)*m+y];
        int x1 = x+1, x2 = x-1, y1 = y-1, y2 = y+1;
        while(!vis[x1][y-1]) ++x1;
        while(!vis[x2][y+1]) --x2;
        while(!vis[x+1][y1]) --y1;
        while(!vis[x-1][y2]) ++y2;
        for(int xx = x+1; xx < x1; ++xx)
            for(int yy = y-1; yy > y1; --yy)
                vis[xx][yy] = true;
        for(int xx = x-1; xx > x2; --xx)
            for(int yy = y+1; yy < y2; ++yy)
                vis[xx][yy] = true;
    }
    for(int i = 1; i <= n+m-1; ++i) 
        printf("%d ", ans[i]);
    return 0;
}

UOJ #7. 【NOI2014】购票

AC Time:2026-04-21 21:21:35

发现我们需要查链上的 \(\min f_{p_i}\),链的其中一个端点为 \(1\)。我们可以使用树剖套李超树,但是 \(\mathrm O(n \log^3 n)\),过个鬼的 \(n \le 2 \times 10^5\)

查看题解发现一个 trick:先 DFS 一遍制造一个出栈序 \(\text{idx}_i\)(如果你不知道什么是出栈序,参见代码中的 dfs1 函数),然后再 DFS 一遍,那么 dfs 到 \(u\) 时,对于点 \(u, v\),其中 \(v\)\(u\) 的祖先,\([\text{idx}_u, \text{idx}_v]\) 的点要么在链 \(u - v\) 上,要么没有被预处理。

然后我们只需要使用线段树套李超树即可,复杂度 \(\mathrm O(n \log^2 n)\)

#include <bits/stdc++.h>
#define llong long long
#define N 200005
using namespace std;

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int n, tid;

vector<int> G[N];
llong l[N], p[N], q[N];
llong dep[N], dp[N];
int fa[N][21], idx[N], idcnt;

int tmp[N], m;

namespace LiChaoSegT{
    struct Seg{llong k, b; bool vis;};
    #define get(s,x) (s.vis ? s.k*x+s.b : (llong)1e18+3)

    Seg val[N<<6];
    int ls[N<<6], rs[N<<6], tsiz;
    #define mid ((l+r)>>1)

    class LiChaoTree{
        int root;

        inline void insert(Seg k1, int &x, int l = 1, int r = m){
            if(!x) x = ++tsiz;
            if(!val[x].vis){val[x] = k1; return;}
            Seg k2 = val[x];
            if(get(k1, tmp[mid]) < get(k2, tmp[mid])) swap(k1, k2);
            val[x] = k2;
            if(get(k1, tmp[l]) < get(k2, tmp[l])) insert(k1, ls[x], l, mid  );
            if(get(k1, tmp[r]) < get(k2, tmp[r])) insert(k1, rs[x], mid+1, r);
            return;
        }
        inline llong getmin(int pos, int &x, int l = 1, int r = m){
            if(!x) return (llong)1e18+3;
            if(l == r) return get(val[x], tmp[pos]);
            if(pos <= mid) return min(get(val[x], tmp[pos]), getmin(pos, ls[x], l, mid  ));
            else           return min(get(val[x], tmp[pos]), getmin(pos, rs[x], mid+1, r));
        }

        public:
        inline void insert(Seg k1){insert(k1, root);};
        inline llong getmin(int pos){return getmin(pos, root);}
    };

    LiChaoTree root[N<<2];
    #define ls(x) (x<<1)
    #define rs(x) (x<<1|1)
    inline void insert(int pos, Seg k, int x = 1, int l = 1, int r = n){
        root[x].insert(k);
        if(l == r) return;
        if(pos <= mid) insert(pos, k, ls(x), l, mid  );
        else           insert(pos, k, rs(x), mid+1, r);
    }
    inline llong getmin(int L, int R, int pos, int x = 1, int l = 1, int r = n){
        if(L <= l && R >= r) return root[x].getmin(pos);
        if(R <= mid) return getmin(L, R, pos, ls(x), l, mid  );
        if(L >  mid) return getmin(L, R, pos, rs(x), mid+1, r);
        return min(getmin(L, R, pos, ls(x), l, mid), getmin(L, R, pos, rs(x), mid+1, r));
    }
}
using LiChaoSegT::Seg;
using LiChaoSegT::getmin;
using LiChaoSegT::insert;

inline void dfs1(int u){
    for(int v : G[u]) dfs1(v);
    idx[u] = ++idcnt;
    return;
}
inline void dfs2(int u){
    if(u != 1){
        int v = u;
        for(int i = 20; ~i; --i)
            if(dep[u]-dep[fa[v][i]] <= l[u]) v = fa[v][i];
        dp[u] = getmin(idx[u], idx[v], lower_bound(tmp+1, tmp+m+1, p[u])-tmp)+(dep[u]*p[u]+q[u]);
        insert(idx[u], {-dep[u], dp[u], true});
    }
    else insert(n, {0, 0, true});
    for(int v : G[u]) dfs2(v);
    return;
}

int main(){
    read(n, tid);
    for(int i = 0; i <= 20; ++i) fa[1][i] = 1;
    for(int i = 2; i <= n; ++i){
        read(fa[i][0], dep[i], p[i], q[i], l[i]);
        dep[i] += dep[fa[i][0]];
        for(int j = 1; j <= 20; ++j)
            fa[i][j] = fa[fa[i][j-1]][j-1];
        G[fa[i][0]].push_back(i);
        tmp[i] = p[i];
    }
    sort(tmp+1, tmp+n+1), m = unique(tmp+1, tmp+n+1)-tmp-1;
    dfs1(1), dfs2(1);
    for(int i = 2; i <= n; ++i) printf("%lld\n", dp[i]);
    return 0;
}

UOJ #8. Quine

AC Time:2026-04-21 21:49:40

Quine. 没什么好说的。

#include <stdio.h>
int main(){
    char s[] = "#include <stdio.h>%cint main(){%c    char s[] = %c%s%c;%c    printf(s, 10, 10, 34, s, 34, 10, 10, 10);%c}%c";
    printf(s, 10, 10, 34, s, 34, 10, 10, 10);
}

UOJ #9. 【UTR #1】vfk的数据

AC Time:2026-04-21 22:19:31

发现题目就是一个高精度数比较,直接用 string 存一下数,sort 一下就行了。

#include <bits/stdc++.h>
#define llong long long
#define N 100005
using namespace std;

string a[N];

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
inline void read(char* x){
    *x = gc();
    while(*x == ' ' || *x == '\r' || *x == '\n') *x = gc();
    while(*x < '0' || *x > '9') *++x = gc();
    *x = '\0', --p1;
}
inline void read(string& x){
    char ch = gc();
    while(ch < '0' || ch > '9') ch = gc();
    while(ch >= '0' && ch <= '9')
        x += ch, ch = gc();
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int n;
char s[N];

int main(){
    read(n, s);
    for(int i = 1; i <= n; ++i) read(a[i]);
    sort(a+1, a+n+1, [&](string o1, string o2){return o1.size()==o2.size() ? o1<o2 : o1.size()<o2.size();});
    for(int i = 1; i <= n; ++i)
        cout << s << a[i] << ".in\n";
    return 0;
}

UOJ #10. 【UTR #1】pyx的难题

AC Time:2026-04-22 21:50:57

发现赋给特殊题目的权值越高完成就越快,我们可以直接二分答案。

\(\mathrm O(n \log^2 n)\),不知道为什么过 \(3 \times 10^5\) 需要大力卡常。

#include <bits/stdc++.h>
#define llong long long
#define N 300005
using namespace std;

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int n, m, sp; llong T, k;
struct Node{
    llong t; 
    mutable llong s;
    int p, id;
} a[N];
llong ans[N];
llong tmp[N], ark[N];

__always_inline bool operator<(const Node& o1, const Node& o2){return o1.p<o2.p;}
__always_inline bool operator>(const Node& o1, const Node& o2){return o1.p>o2.p;}
__always_inline bool operator<=(const Node& o1, const Node& o2){return o1.p<=o2.p;}
__always_inline bool operator>=(const Node& o1, const Node& o2){return o1.p>=o2.p;}

Node heap[N]; int top;
__always_inline void adjust(int x){
    for(; x != 1; x >>= 1){
        if(heap[x].p > heap[x>>1].p) swap(heap[x], heap[x>>1]);
        else break;
    }
    return;
}
__always_inline void pop(){
    if(top == 1) return top = 0, void();
    int x = 1;
    heap[1] = heap[top--];
    while((x<<1) <= top){
        if((x<<1|1) > top){
            if(heap[x] < heap[x<<1]) swap(heap[x], heap[x<<1]);
            break;
        }
        if(heap[x<<1] >= heap[x<<1|1] && heap[x<<1] > heap[x]) swap(heap[x], heap[x<<1]), x = x<<1;
        else if(heap[x<<1|1] >= heap[x<<1] && heap[x<<1|1] > heap[x]) swap(heap[x], heap[x<<1|1]), x = x<<1|1;
        else break;
    }
    return;
}

__always_inline int check(int k){
    a[sp].p = k;
    top = 0;
    for(int i = 1; i <= n; ++i){
        heap[++top] = a[i], adjust(top);
        llong t = a[i+1].t-a[i].t;
        while(top && t){
            if(t >= heap[1].s){
                t -= heap[1].s;
                if(a[i+1].t-t > T)              return -1;
                else if(heap[1].id == a[sp].id) return a[i+1].t-t < T;
                pop();
            }
            else heap[1].s -= t, t = 0;
        }
    }
    assert(false);
    return false;
}

int main(){
    read(n);
    for(int i = 1; i <= n; ++i){
        read(a[i].t, a[i].s, a[i].p);
        tmp[i-1] = a[i].p;
        a[i].id = i;
    }
    a[n+1] = {(llong)1e18+3, 0, 0, 0};
    read(T);
    sort(a+1, a+n+1, [&](Node o1, Node o2){return o1.t<o2.t;});
    for(int i = 1; i <= n; ++i)
        if(a[i].p == -1) sp = i;
    tmp[n] = 0;
    sort(tmp, tmp+n+1);
    for(int i = 1; i <= n; ++i)
        if(tmp[i]+1 != tmp[i+1]) ark[++m] = tmp[i]+1;
    int l = 1, r = m;
    while(l < r){
        int mid = (l+r)>>1;
        int op = check(ark[mid]);
        if(op == 0){
            l = r = mid;
            break;
        }
        if(op == -1) l = mid+1;
        else         r = mid-1;
    }
    a[sp].p = ark[l];
    top = 0;
    for(int i = 1; i <= n; ++i){
        heap[++top] = a[i], adjust(top);
        llong t = a[i+1].t-a[i].t;
        while(top && t){
            if(t >= heap[1].s){
                t -= heap[1].s;
                ans[heap[1].id] = a[i+1].t-t;
                pop();
            }
            else heap[1].s -= t, t = 0;
        }
    }
    printf("%lld\n", ark[l]);
    for(int i = 1; i <= n; ++i) printf("%lld ", ans[i]);
    return 0;
}

UOJ #11. 【UTR #1】ydc的大树

AC Time:2026-04-23 20:44:26

好玩的分讨题,让我 1d 就做了一个题。

我们发现最远黑点必定是黑直径的端点,我们考虑这些直径。

我们考虑树的中心,以下称“侧”为以树的中心为根在哪个子树里,那么发现一个点的最远点必定和它在不同侧。

发现中心可以是点或者边,于是分讨以下即可。

细节不想讲了看代码吧,这题真的给我神秘到了。

#include <bits/stdc++.h>
#define llong long long
#define N 100005
using namespace std;

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int n, m;
int col[N];
vector<pair<int, int>> G[N];
int a[N], b[N], siz[N], tsiz[N], dep[N], ans[N], pcnt;

inline pair<int, int> dfs1(int u, int fa = 0, int dis = 0){
    pair<int, int> res;
    if(col[u]) res = make_pair(dis, u);
    else       res = make_pair(-1e9-7, -1e9-7);
    for(auto tmp : G[u]){
        int v = tmp.first, w = tmp.second;
        if(v == fa) continue;
        res = max(res, dfs1(v, u, dis+w));
    }
    return res;
}
inline bool dfs2(int u, int fa, int dest, int dist){
    if(u == dest) return true;
    for(auto tmp : G[u]){
        int v = tmp.first, w = tmp.second;
        if(v == fa) continue;
        if(!dfs2(v, u, dest, dist-w)) continue;
        ++pcnt, a[pcnt] = u, b[pcnt] = dist;
        return true;
    }
    return false;
}
inline void dfs3(int u, int fa, int tar, int dis = 0){
    siz[u] = col[u];
    dep[u] = col[u] ? 0 : -1e9-7;
    tsiz[u] = (dis==tar)&&col[u];
    for(auto tmp : G[u]){
        int v = tmp.first, w = tmp.second;
        if(v == fa) continue;
        dfs3(v, u, tar, dis+w);
        dep[u] = max(dep[u], dep[v]+w);
        siz[u] += siz[v], tsiz[u] += tsiz[v];
    }
    return;
}
inline void dfs4(int u, int fa, int ss, int delta){
    if(!siz[u]) return;
    if(!col[u]) ans[u] = siz[u]+(tsiz[u]==ss)*delta;
    for(auto tmp : G[u]){
        int v = tmp.first;
        if(v == fa) continue;
        dfs4(v, u, ss, delta);
    }
    return;
}

int main(){
    read(n, m);
    for(int i = 1, x; i <= m; ++i)
        read(x), col[x] = true, ans[x] = -1;
    for(int i = 1; i < n; ++i){
        int u, v, w; read(u, v, w);
        G[u].emplace_back(v, w);
        G[v].emplace_back(u, w);
    }
    int u, v, w;
    u = dfs1(1).second;
    tie(w, v) = dfs1(u);
    a[++pcnt] = u;
    dfs2(v, 0, u, w);
    int mid = 1;
    while(b[mid]*2 < w) ++mid;
    if(b[mid]*2 == w){
        int d = b[mid], cnt = 0, sid = col[a[mid]];
        mid = a[mid];
        if(!col[mid]) ans[mid] = m;
        dfs3(mid, 0, d);
        for(auto now : G[mid]){
            if(dep[now.first] == d-now.second) ++cnt;
            else sid += siz[now.first];
        }
        for(auto now : G[mid]){
            int u = now.first;
            dfs4(u, mid, tsiz[u], ((cnt==2)&&(dep[now.first] == d-now.second)) ? (m-siz[u]-sid) : 0);
        }
    }
    else{
        int d1 = b[mid-1], d2 = w-b[mid];
        int mid1 = a[mid-1], mid2 = a[mid];
        dfs3(mid1, mid2, d1), dfs3(mid2, mid1, d2);
        dfs4(mid1, mid2, tsiz[mid1], m-siz[mid1]);
        dfs4(mid2, mid1, tsiz[mid2], m-siz[mid2]);
    }
    sort(ans+1, ans+n+1, greater<int>());
    int cnt = 1;
    while(ans[cnt] == ans[1]) ++cnt;
    printf("%d %d", ans[1], cnt-1);
    return 0; 
}

UOJ #12. 【UER #1】猜数

AC Time:2026-04-23 21:11:03

好水的题。

因为 \(ab = gl = n\),设 \(a = gk_1, b = gk_2\),那么 \(l = gk_1k_2\)。问题转化为给定 \(k_1k_2\),求 \(k_1 + k_2\) 的最值,保证 \(k_1k_2\) 为完全平方数。

然后就是小学数学题了。

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

llong a, b;

int _main(){
    cin >> a >> b;
    cout << a*(llong)sqrt(b/a)*2 << " " << a+b << endl;
    return 0;
}

int T;
int main(){
    cin >> T;
    while(T--) _main();
    return 0;
}

posted @ 2026-04-16 18:04  Hootime  阅读(13)  评论(0)    收藏  举报