• 20201003day25 模拟(五)


    1

    贪心。在每一位(i)的之后,寻找(L=min(n-i,k))-意思是如果操作数(k)足够大,我可以在剩下的数中寻找字典序较小,否则在之后的(k)个字符中寻找较小。

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    using namespace std;
    long long n,k;
    string a;
    string find(string num,long long k){
    	if(k==0) return "";
    	if(num.size()*num.size()<k) {sort(num.begin(),num.end());return num;}
    	int cur=0,next=0;
    	for(int i=0;i<num.length();i++){
    		int index=0;
    		bool flag=false;
    		int tmp=num[i];
    		for(int m=i+1;m<i+1+k&&m<num.size();m++){
    			if(tmp>num[m]){
    				tmp=num[m];
    				index=m;
    				flag=true;
    			}
    		}
    		if(flag){
    			for(int j=index;j>=1;j--){
    				if(num[j]<num[j-1]){
    					swap(num[j],num[j-1]);
    					k--;
    				}
    				if(k==0) return num;
    			}
    			flag=false;
    		}
    	}
    	return num;
    }
    int main(){
    	freopen("escape.in","r",stdin);
    	freopen("escape.out","w",stdout);
    	scanf("%lld%lld",&n,&k);
    	cin>>a;
    	if(k==0){
    		cout<<a;
    		return 0;
    	}
    	cout<<find(a,k);
    	return 0;
    }
    

    线段树树状数组优化

    将字符转为数字串,我们来看原串和答案串:

    答案串[ ][ ][ ][ ][ ][ ][ ]
    原来串[a][b][a][b][a][a][b]


    答案串[a][ ][ ][ ][ ][ ][ ]
    原来串[x][b][a][b][a][a][b]


    答案串[a][a][ ][ ][ ][ ][ ]
    原来串[x][b][x][b][a][a][b]


    答案串[a][a][a][ ][ ][ ][ ]
    原来串[x][b][x][b][x][a][b]


    [若此时(k)无法使得最后一个a挪到前面,则移动第二位的b]

    答案串[a][a][a][b][ ][ ][ ]
    原来串[x][x][x][b][x][a][b]

    最后使用树状数组维护挪到前面所需要的步数,如果有字符就为1,没有为0,求前缀和就好。
    寻找最小字符貌似是枚举?

    2

    三个(O(n))输出

    菊花图

    每条路径一定是从叶节点到菊花的中心,再到另一个叶子,且只经过 3 个节点。设有 (s) 个叶节点的海拔小于菊花的中心,答案就是((_2^s))

    枚举路径的海拔最高点。通过递推求出从该点出发往两侧的最长单调下降序列长度(L_1, L_2),那么以该点为最高点的合法路径数量为 (L_1 imes L_2)

    看作以 (n) 为根的有根树,每个点 (x) 都满足(fa_x > x)

    (n) 作为根。注意到一条路径合法,当且仅当这条路径上深度最小的点不是路径的端点。枚举路径上深度最小的点,统计端点位于该点的两棵不同子树中的路径数量即可。

    正解

    先通过递推求出从每个点出发,海拔单调下降的路径数量。对于每个点 (x),设从 (x) 出发,到每棵子树中的海拔单调下降的路径数量分别为 (s_1, ..., s_k),那么以该点为海拔最高点的合法路径数量为

    [left(sum_{i=1}^ks_i ight)^2-sum_{i=1}^ks_i^2 ]

    将所有点的贡献相加就是答案。

    反思

    二叉树想出来了。多叉想错了。哭。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    
    const int N = 300005;
    
    int n, f[N];
    vector<int> e[N];
    
    int main()
    {
    	freopen("ride.in", "r", stdin);
    	freopen("ride.out", "w", stdout);
    	scanf("%d", &n);
    	for (int i = 1; i < n; i++)
    	{
    		int x, y; scanf("%d%d", &x, &y);
    		e[x].push_back(y); e[y].push_back(x);
    	}
    	LL ans = 0;
    	for (int i = 1; i <= n; i++)
    	{
    		for (int x : e[i]) if (x < i) f[i] += f[x] + 1;
    		for (int x : e[i]) if (x < i) ans += (LL)(f[i] - f[x] - 1) * (f[x] + 1);
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
    要做就做南波万
  • 相关阅读:
    sysaux 过大如何清理释放空间
    oracle获取当前时间前半小时和整点的时间
    在Mac OS 下 npm install 报权限不足的错误
    基于 NPOI + 反射的Excel导入帮助类
    从零开始 MongoDB 集群(ReplSet)搭建 之一 MongoDB的安装
    使用Swagger导入cvs文件出现乱码的解决办法
    基于DynamicExpresso的自定义表达式计算
    从零开始 MongoDB 集群(ReplSet)搭建 之二 群集搭建
    halcon视觉入门钢珠识别
    纯前端如何在网页端播放摄像头的实时画面
  • 原文地址:https://www.cnblogs.com/liuziwen0224/p/20201003day25-001.html
Copyright © 2020-2023  润新知