• Codeforces Round #635 (Div.1) 题解 (ABC)


    比赛链接:https://codeforces.com/contest/1336

    A. Linova and Kingdom

    贪心

    显然不会出现某个旅游城市的父亲是工业城市的情况(因为它俩交换一下就会有更大收益),因此最优解一定是工业城市远离根,旅游城市靠近根

    在上述情况下尝试着把一个(父亲是旅游城市的)工业城市变成旅游城市(好绕啊),会发现happiness变化量等于这个结点为根的子树大小,减去这个结点的深度

    因此让所有城市刚开始都是工业城市,把根放入优先队列中,然后每次取出happiness变化量最大的结点并将其儿子放入优先队列中

    #include <bits/stdc++.h>
    using namespace std;
    #define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
    #define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
    #define vector basic_string
    int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
    const int N=200010; typedef long long ll;
    #define int ll
    int sz[N],dep[N];
    bool vis[N];
    vector<int> a[N];
    void dfs(int x){
    	vis[x]=1;
    	sz[x]=1;
    	for(auto p:a[x])
    	if(!vis[p]){
    		dep[p]=dep[x]+1;
    		dfs(p);
    		sz[x]+=sz[p];
    	}
    }
    int f(int x){
    	return sz[x]-dep[x];
    }
    int n,k;
    priority_queue<pair<ll,ll>> q;
    signed main(){
    	cin>>n>>k;
    	repeat(i,0,n-1){
    		int x,y; cin>>x>>y; x--,y--;
    		a[x]+=y;
    		a[y]+=x;
    	}
    	dep[0]=1;
    	dfs(0);
    	ll ans=0;
    	q.push({f(0),0});
    	fill(vis,vis+n,0);
    	repeat(i,0,n-k){
    		ans+=q.top().first;
    		int x=q.top().second; q.pop(); vis[x]=1;
    		for(auto p:a[x])
    		if(!vis[p])
    			q.push({f(p),p});
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

    B. Xenia and Colorful Gems

    目前有两种方法(群里大佬说的forforfor可能是第三种方法但是我没听懂)

    首先对三个数组a,b,c排序,然后遍历数组a,在数组b中二分查找出最接近 (a[i]) 的两个数(一个大于等于,一个小于等于)(b[j_1],b[j_2]),然后在数组c中二分查找出最接近 (dfrac{a[i]+b[j_1]}2) 的两个数 (c[k_{11}],c[k_{12}]),以及最接近 (dfrac{a[i]+b[j_2]}2) 的两个数 (c[k_{21}],c[k_{22}]),更新一下答案(这样会更新4次)。最后,把数组b和c交换一下重复上述操作

    第二种方法优雅很多,即排序后每个数组弄一个指针(指向数组头),考虑三个指针向后移动的三个答案(没有真的移动),哪个答案小就移动哪个(这才是真的移动),边跑边更新答案

    两个方法都贴出来了

    #include <bits/stdc++.h>
    using namespace std;
    #define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
    #define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
    int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
    const int N=200010; typedef long long ll; const ll INF=~0ull>>2;
    #define int ll
    vector<int> a,b,c;
    ll ans;
    template<typename T> T sqr(const T &x){return x*x;}
    void up(int x,int y,int z){
    	ans=min(ans,sqr(x-y)+sqr(y-z)+sqr(z-x));
    }
    void work2(int A,int B,const vector<int> &c){
    	int mid=(A+B)/2;
    	int ci=lower_bound(c.begin(),c.end(),mid)-c.begin();
    	if(ci!=(int)c.size())up(A,B,c[ci]);
    	if(ci!=0)up(A,B,c[ci-1]);
    }
    void work(int A,const vector<int> &b,const vector<int> &c){
    	int bi=lower_bound(b.begin(),b.end(),A)-b.begin();
    	if(bi!=(int)b.size())work2(A,b[bi],c);
    	if(bi!=0)work2(A,b[bi-1],c);
    }
    signed main(){
    	int T; cin>>T;
    	while(T--){
    		ans=INF*2;
    		{
    			int n1,n2,n3,x; cin>>n1>>n2>>n3;
    			a.clear(); b.clear(); c.clear();
    			repeat(i,0,n1)cin>>x,a.push_back(x);
    			repeat(i,0,n2)cin>>x,b.push_back(x);
    			repeat(i,0,n3)cin>>x,c.push_back(x);
    		}
    		sort(a.begin(),a.end());
    		sort(b.begin(),b.end());
    		sort(c.begin(),c.end());
    		repeat(i,0,a.size()){
    			work(a[i],b,c);
    			work(a[i],c,b);
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
    #include <bits/stdc++.h>
    using namespace std;
    #define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
    #define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
    int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
    const int N=200010; typedef long long ll; const ll INF=~0ull>>2;
    #define int ll
    vector<int> a,b,c;
    ll ans;
    template<typename T> T sqr(const T &x){return x*x;}
    int cal(int x,int y,int z){
    	return sqr(x-y)+sqr(y-z)+sqr(z-x);
    }
    template<typename T>
    int pcal(T x,T y,T z){
    	return cal(*x,*y,*z);
    }
    signed main(){
    	int T; cin>>T;
    	while(T--){
    		ans=INF*2;
    		{
    			int n1,n2,n3,x; cin>>n1>>n2>>n3;
    			a.clear(); b.clear(); c.clear();
    			repeat(i,0,n1)cin>>x,a.push_back(x);
    			repeat(i,0,n2)cin>>x,b.push_back(x);
    			repeat(i,0,n3)cin>>x,c.push_back(x);
    		}
    		sort(a.begin(),a.end());
    		sort(b.begin(),b.end());
    		sort(c.begin(),c.end());
    		auto p1=a.begin(),p2=b.begin(),p3=c.begin();
    		while(1){
    			int now=INF*2; auto nowp=&p1; ans=min(ans,pcal(p1,p2,p3));
    			if(p1!=a.end()-1 && pcal(p1+1,p2,p3)<now)now=pcal(p1+1,p2,p3),nowp=&p1;
    			if(p2!=b.end()-1 && pcal(p1,p2+1,p3)<now)now=pcal(p1,p2+1,p3),nowp=&p2;
    			if(p3!=c.end()-1 && pcal(p1,p2,p3+1)<now)now=pcal(p1,p2,p3+1),nowp=&p3;
    			if(now==INF*2)break;
    			(*nowp)++;
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

    C. Kaavi and Magic Spell

    这个是区间dp,而且真的不难,不要被它的位置吓到了(我承认我被吓到了

    首先把字符串 (T) 的尾部加上特殊字符让它的长度和 (S) 相等(比 (S) 还长更好,雾),然后考虑状态转移方程

    如果我们已经生成了 (T) 的某个子串 (t),那么就可以把 (S[len(t)]) 插入 (t) 的前面或者后面,这时候要考虑是否匹配(即 (T)(t) 的前面或者后面是否等于 (S[len(t)])),方案数也随之转移

    因此 (dp[l][r]) 表示生成 (T[l..r]) 有多少方案数,就有 (dp[l,r]=dp[l+1][r] imes[是否匹配]+dp[l][r-1] imes[是否匹配])(具体懒得写了,看代码吧)

    可以自上而下的记忆化搜索,也可以自下而上的标准动规(比赛时我记忆化写炸了所以换成dp了)

    #include <bits/stdc++.h>
    using namespace std;
    #define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
    #define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
    int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
    const int N=3010; typedef long long ll;
    const int mod=(0?1000000007:998244353);
    #define int ll
    string s,t;
    int rec[N][N],n,final;
    signed main(){
    	cin>>s>>t; t+=string(s.size()-t.size()+1,'?');
    	n=s.size();
    	repeat(i,0,n+1)rec[i][i]=1;
    	repeat(len,1,n+1){
    		repeat(l,0,n)
    		if(l+len<=n){
    			int r=l+len; //注意注意注意这里区间是左闭右开的,即 T[l..(r-1)]
    			ll ans=0;
    			if(t[l]=='?' || s[len-1]==t[l])ans+=rec[l+1][r];
    			if(t[r-1]=='?' || s[len-1]==t[r-1])ans+=rec[l][r-1];
    			rec[l][r]=ans%mod;
    		}
    	}
    	repeat(i,0,n+1)
    	if(t[i]=='?')
    		final=(final+rec[0][i])%mod;
    	cout<<final<<endl;
    	return 0;
    }
    

    E1想假了,等官方题解出来了再更新/kk

    更:我能看懂E1的题解,但是代码根本写不来,那就不更了23333

  • 相关阅读:
    【转载】zookeeper数据模型
    java.util.logging使用笔记2
    spark提交应用的方法(spark-submit)
    spark集群模式概述
    [spark]spark 编程教程
    [spark]Spark Streaming教程
    使用github pages创建博客
    spark 编程教程
    Spark编程指南V1.4.0(翻译)
    mysql基本操作
  • 原文地址:https://www.cnblogs.com/axiomofchoice/p/12712912.html
Copyright © 2020-2023  润新知