• "蔚来杯"2022牛客暑期多校训练营3


    是我太菜了 加上补提也才三个题

    A

    Ancestor

    题目主要是让我们求长度为k-1的点集的最近公共祖先(一个点被删了)

    方法一用到结论 我们只用取这些点中dfs序最小和最大的两个点来求最近公共祖先就行。

    方法二可以维护一个前缀和后缀lca数组 每次删除该点 相当于是求lca(pre[i-1],suf[i+1])

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    typedef pair <int, int> PII;
    typedef unsigned long long ull;
    const double pi=acos(-1.0);
    const long long inf=0x3f3f3f3f3f3f3f3f;
    const double epsn=1e-9;
    const ll modp=1e9+7;
    const int maxn=1e5+5;
    
    ll a[maxn];
    int f[maxn][30],dep[maxn],dfn[maxn];ll va[maxn];
    int p[2][maxn],n,k;
    vector<int> g[maxn];
    int cnt=0;
    void dfs(int u,int fa){
    	f[u][0]=fa;
    	dep[u]=dep[fa]+1;
    	cnt++;
    	dfn[u]=cnt;
    	for(int i=1;(1<<i)<=dep[u];i++){
    		f[u][i]=f[f[u][i-1]][i-1];
    	}
    	for(auto i:g[u]){
    		if(i==fa)continue;
    		dfs(i,u);
    	}
    }
    
    int lca(int u,int v){
    	if(dep[u]<dep[v]){int t=u;u=v;v=t;}
    	for(int i=log2(dep[u]-dep[v]);i>=0;i--){
    		if(dep[f[u][i]]>=dep[v])u=f[u][i];
    	}
    	if(u==v)return u;
    	
    	for(int i=log2(dep[u]);i>=0;i--){
    		if(f[u][i]!=f[v][i]){
    			u=f[u][i];v=f[v][i];
    		}
    	}
    	return f[u][0];
    }
    bool cmp(int a,int b){
    	return dfn[a]<dfn[b];
    }
    void solve(int temp){
    	for(int i=1;i<=n;i++){
    		cin>>va[i];
    		g[i].clear();
    	}
    	for(int i=2;i<=n;i++){
    		int x;cin>>x;g[x].push_back(i);
    	}
    	cnt=0;
    	dfs(1,0);
    	sort(a+1,a+1+k,cmp);
    	int x=lca(a[2],a[k]);p[temp][a[1]]=va[x];
    	x=lca(a[1],a[k-1]);p[temp][a[k]]=va[x];
    	x=lca(a[1],a[k]);
    	for(int i=2;i<=k-1;i++){
    	    p[temp][a[i]]=va[x];
    	}
    }
    int main()
    {
    	cin>>n>>k;
    	for(int i=1;i<=k;i++)cin>>a[i];
    	solve(0);solve(1);
    	int ans=0;
    	for(int i=1;i<=k;i++){
    		if(p[0][a[i]]>p[1][a[i]])ans++;
    	}
    	cout<<ans;
    }
    

    C
    Concatenation

    这个题和P1012 [NOIP1998 提高组] 拼数 一模一样

    https://www.luogu.com.cn/problem/P1012

    题意很清楚。只有贪心就可以了。即(如果b+a>a+b 则交换位置)?

    有同学会问为什么不直接比较a和b呢?下面举个例子:

    当输入:2

    300 30时

    易知答案为30300。

    可是如果单纯的字符串比较,那么答案为30030

    现在才知道 原来string可以直接用比较符号比较大小

    #include <bits/stdc++.h>
    using namespace std;
    string s[2000005];
    bool cmp(string a,string b){return a+b<b+a;}
    int main() {
        ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
        int n;cin>>n;
        for(int i=0;i<n;i++) cin>>s[i];
        sort(s,s+n,cmp);
        for(int i=0;i<n;i++) cout<<s[i];
        return 0;
    }
    

    J
    Journey

    模拟题

    直接bfs一波就好

    #include <bits/stdc++.h>
    using namespace std;
    struct inf{
    public:
    	int u;
    	int v;
    	int cst;
    };
    int main(){
    	int n;scanf("%d",&n);
    	vector<vector<int>> li(n+1,vector<int>(5));
    	vector<vector<int>> ale(n+1,vector<int>(5));
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=4;j++)
    			scanf("%d",&li[i][j]);
    	int s1,s2,t1,t2;scanf("%d%d%d%d",&s1,&s2,&t1,&t2);
    	deque<inf> que;
    	que.push_front({s1,s2,0});
    	int ans=2147483647;
    	while(!que.empty()){
    		inf info=que.front();que.pop_front();
    		int u=info.u,v=info.v,cst=info.cst;
            if(u==t1&&v==t2)ans=min(ans,cst);
    		int pos=0;
    		for(int i=1;i<=4;i++)if(li[v][i]==u)pos=i;
    		if(ale[v][pos]++)continue;
            que.push_front({v,li[v][pos%4+1],cst});
    		for(int i=1;i<=4;i++){
    			que.push_back({v,li[v][i],cst+(i==pos%4+1?0:1)});
    		}
    	}
    	printf("%d",ans==2147483647?-1:ans);
    }
    
    
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Oracle数据库基础
    软件项目开发模式——三层模式
    JavaWeb——Ajax与MVC学习总结
    JavaWeb——EL及JSTL学习总结
    JavaWeb——过滤器及监听器
    JavaWeb——Servlet开发
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16539016.html
Copyright © 2020-2023  润新知