某岛

… : "…アッカリ~ン . .. . " .. .
February 7, 2023

The 1st Universal Cup, Stage 2, Hongkong

Problem A. TreeScript

简单树 dp。

const int N = int(1e6) + 9;
VI adj[N]; int dp[N];
int n, z;

void dfs(int u) {
    dp[u] = 0;
    for (auto v: adj[u]) {
        dfs(v);
        checkMax(dp[u], dp[v] + 1);
    }

    int c = 0;
    for (auto v: adj[u]) {
        if (dp[u] == dp[v] + 1) ++c;
    }
    if (c == 1) dp[u] -= 1;

}

int main(){

#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
#endif

    Rush {
        RD(n);
        REP_1(i, n) adj[i].clear();
        REP_1(i, n)  adj[RD()].PB(i);
        dfs(1); cout << dp[1] + 1 << endl;
    }
}

Problem B. Big Picture

第一反应是每个格点独立染色。。。。卧槽这能做?
然后发现是每一行和每一列都独立染色。。。哦。。。那样黑色一定只有一个连通块,且每个白色块都是矩形。。有且仅有一个右下角。。
那么还是可以利用期望的线性性。。考察每个点成为白色区域的右下角的概率即可。。。

Problem E. Goose, goose, DUCK?

不知为何,让我想到了 dQuery。先考虑对答案取反,那么显然就是维护区间并的测度,线段树即可。

做法也类似,对每种数字,开个 queue 记录前面出现的位置。
然后找到插入新数字前后变化的区间,操作线段树即可。

const int N = int(1e6) + 9;
int n;

struct rec{
    int cov, cnt;
} T[8*N];


#define lx (x<<1)
#define rx (lx|1)
#define ml ((l+r)>>1)
#define mr (ml+1)
#define lc lx,l,ml
#define rc rx,mr,r


void upd(int x, int l, int r) {
    if (T[x].cnt > 0) T[x].cov = r - l + 1;
    else T[x].cov = T[lx].cov + T[rx].cov;
}

void inc(int x, int d) {
    T[x].cnt += d;
}


/*int Query(int x, int l, int r, const int a, const int b) {
    if (b < l || r < a) return 0;
    if (a <= l && r <= b) {
        return T[x];
    } else {
        return min(Query(lc, a, b), Query(rc, a, b), cmp);
    }
}*/

void Add(int x, int l, int r, int a, int b, int d) {
    if (b < l || r < a) return;
    if (a <= l && r <= b) {
        inc(x, d);
    } else {
        Add(lc, a, b, d);
        Add(rc, a, b, d);
    }
    upd(x,l,r);
}

map<int, VI> H;
int m;

void gao(int x, int d) {

#define t H[x]

    if (SZ(t) < m) return;
    if (SZ(t) == m) {
        int l = 1, r = t[0];
        Add(1, 1, n, l ,r ,d);  // m-1
    } else { // 0..m ,
        int l = t[SZ(t)-(m+1)]+1, r = t[SZ(t)-m];
        Add(1, 1, n, l ,r ,d);
    }
}


int main(){

#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
#endif

    RD(n, m);
    LL z = 0;
    REP_1(i, n) {
        int x; RD(x);

        gao(x, -1);
        H[x].PB(i);
        gao(x, 1);

        z += i - T[1].cov;
    }
    cout << z <<endl;
}

Problem F. Sum of Numbers

看起来人畜无害的签到题。。。但是不知为何非常卡时。。。难道是因为高精度太慢?
看了一下其它人的代码。。。貌似 dp 和 搜索都可以过?
dp
搜索

Problem H.

签到题。

int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
//	int p=read();
//	For(i,p)if(p%i!=0) cout<<p%i<<endl;
	ll l,r,b,k;
	cin>>l>>r>>b>>k;
	cout<<((l+b-1)/b)*b*k;
	return 0;
}

Problem K.

签到题。

int main() {
	
	int n=read();
	For(i,n) a[i]=read();
	
	sort(a+1,a+1+n);
	n=unique(a+1,a+1+n)-a-1;
	if(n==1) cout<<a[1]<<endl;	
	else if(a[1]*2<=a[2]) cout<<a[1]<<endl;
	else cout<<min(a[1]/2,a[2]/2)<<endl;
	return 0;
}