• 2019.10.26模拟赛


    T1 序列

    给定一长度为(n)的序列(s),定义其健美值为:$$sumlimits_{i=1}^{n}|s_i - i|$$因为 zzq 喜欢健美,所以 zzq 希望减小(s)的健美值,以衬托 zzq 的健美。为了达到 zzq 的目的,zzq 希望你对序列进行旋转操作,一次旋转操作可以使序列中的所有元素前移一位,并使(s_1)移动到(s_n)
    可以进行任意次旋转操作,zzq 希望旋转后的健美值最小,请找出这个最小值。

    SOV

    智商检测题
    我们发现对于每个数,移动每一次会使原本差小于0的数减少1的贡献,使原先差大于0的增加1的贡献。所以记录大于0的数以及小于0的数的个数,同时维护一个桶记录某一个差值有几个数,用于计算小于0变成大于0时的情况。枚举移动的距离,直接计算即可。

    int main() {
        poread(n);
        for (register int i = 1; i <= n; ++i) poread(a[i]);
        for (register int i = 1; i <= n; ++i) {
            register int x = a[i] - i;
            x >= 0 ? (++cnt1, sum += x) : (++cnt2, sum += -x, ++b[-x]);
        }
        for (register int i = 1; i < n; ++i) {
            register int x = a[i] - 1, y = a[i] - n;
            --cnt1, sum -= x;
            ++cnt2, sum += -y, ++b[-y + i];
            sum += cnt1 - cnt2 + 1;
            if (b[i])
                cnt1 += b[i], cnt2 -= b[i];
            ans = min(ans, sum);
        }
        cout << ans << endl;
    }
    

    T3 动态数点

    zzq 是一个善于思考的好学生。
    于是 zzq 想往他的背包中放序列。
    某一天 zzq 得到了一个长度为(n)的序列({a_i})。然后 zzq 说,如果对于一段区间([L,R]),存在(L leq k leq R)使得(forall i in [L,R])都有(a_k | a_i),我们认为它有价值,价值为(R - L)(若不满足条件则没有价值)。
    现在 zzq 想知道所有区间中价值最大为多少,最大价值的区间有多少个,以及这些区间分别是什么。

    SOV

    ST表维护区间gcd以及区间最小值,二分长度,如果该区间最小值等于区间gcd这个区间就是合法的。
    复杂度(O(n log^2 n))

    inline int gcd(int a,int b)
    {
    	while(b ^= a ^= b ^= a %= b);
    	return a;
    }
    const int MAXN = 5e5 + 10;
    int ST[MAXN][20];
    int TS[MAXN][20];
    int a[MAXN];
    int n;
    int ans[MAXN], tot;
    inline int query(const int &l, const int &r)
    {
    	register int k = log2(r - l + 1);
    	return gcd(ST[l][k], ST[r - (1 << k) + 1][k]);
    }
    inline int yreuq(const int &l, const int &r)
    {
    	register int k = log2(r - l + 1);
    	return min(TS[l][k], TS[r - (1 << k) + 1][k]);
    }
    inline bool check(const int &mid)
    {
    	for(register int l = 1, r = l + mid - 1; r <= n; ++l,++r)
    	{
    		if(query(l, r) == yreuq(l, r))
    			return true;
    	}
    	return false;
    }
    signed main()
    {
    	poread(n);
    	for(register int i = 1; i <= n; ++i)
    		poread(a[i]);
    	for(register int i = 1; i <= n; ++i)
    		ST[i][0] = a[i];
    	int t = log2(n) + 1;
    	for(register int j = 1; j <= t; ++j)
    		for(register int i = 1; i<= n - (1 << j) + 1; ++i)	
    			ST[i][j] = gcd(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
    	for(register int i = 1; i <= n; ++i)
    		TS[i][0] = a[i];
    	for(register int j = 1; j <= t; ++j)
    		for(register int i = 1; i <= n - (1 << j) + 1; ++i)
    			TS[i][j] = min(TS[i][j - 1], TS[i + (1 << (j - 1))][j - 1]);
    	register int l = 2, r = n, mid, res;
    	while(l <= r)
    	{
    		mid = (l + r) >> 1;
    		if(check(mid))
    			res = mid, l = mid + 1;
    		else
    			r = mid - 1;
    	}
    	for(register int i = 1, j = i + res - 1; j <= n; ++i, ++j)
    		if(query(i, j) == yreuq(i, j))
    			ans[++tot] = i;
    	printf("%d %d
    ",tot, res - 1);
    	for(register int i = 1; i <= tot; ++i)
    		printf("%d ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    android 之 ListView相关
    android 之 菜单
    android 之 Dialog
    android 之 View
    android 之 service
    android 之 Intent、broadcast
    Service Broadcast简单音乐播放功能
    剑指offer面试题43:n个筛子的点数
    C# LINQ语法
    C# Linq
  • 原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11745261.html
Copyright © 2020-2023  润新知