zoukankan      html  css  js  c++  java
  • Codeforces Round #686 (Div. 3)

    Codeforces Round #686 (Div. 3)

    Codeforces Round #686 (Div. 3)

    E. Number of Simple Paths

    题意:给一颗基环树,问有多少条路径。

    题解:通过观察易发现,能经过环到达的点都可以走两条路,而在环上的一颗树上的两点都只有一条路径,所以我们可以算出每个点对都走两条路的答案,再减去树上的点对数即可,首先要找到环,我用dfs类似于求强连通分量的方法求出环上的点,在枚举环上有外接树的点用第二个dfs搜出树的大小,更新答案。

        #include<bits/stdc++.h>
        using namespace std;
        #define ll long long
        ll n,t;
        ll ishuan[200007];
        vector<ll>ho[200007];
        vector<ll>res;
        ll vs;
        ll vis[200007];
        ll fa[200007];
        void init(){
        	vs=0;
        	for(int i=1;i<=n;i++)vis[i]=0;
            for(int i=1;i<=n;i++){
            	ho[i].clear();
            	fa[i]=0;
                ishuan[i]=0;
            }
            res.clear();
        }
        void dfs(ll p,ll f){
        	vis[p]=++vs;
            for(int i=0;i<ho[p].size();i++){
                ll to=ho[p][i];
                if(to==f)continue;
                if(vis[to]){
                    if(vis[to]<vis[p])continue;
                    res.push_back(to);
                    ishuan[to]=1;
                    for(;to!=p;to=fa[to]){
                    	res.push_back(fa[to]);
                    	ishuan[fa[to]]=1;
                    }
                }
                else{
                	fa[to]=p;
                	dfs(to,p);
                }
            } 
        }
        ll cal(ll p,ll f){
        	ll sum=1;
        	for(ll i=0;i<ho[p].size();i++){
        		ll to=ho[p][i];
        		if(to==f)continue;
        		sum+=cal(to,p);
        	}
        	return sum;
        }
        int main(){
        	scanf("%lld",&t);
        	while(t--){
        		scanf("%lld",&n);
        	    init();
        	    for(int i=1;i<=n;i++){
        	        int a,b;
        	        cin>>a>>b;
        	        ho[a].push_back(b);
           			ho[b].push_back(a);
        	    }
        	    dfs(1,0);
        	    ll ans=n*(n-1);
        	    for(int i=0;i<res.size();i++){
        	    	int p=res[i];
        	    	ll sum=0;
        	        for(int j=0;j<ho[p].size();j++){
        	        	int to=ho[p][j];
        	        	if(ishuan[to]==0){
        	        		sum+=cal(to,p);
        	        		
        	        	}
        	        }
        	        ans-=sum*(sum+1)/2;
        	    }
        	    printf("%lld
    ",ans);
        	}
        }
    
    F. Array Partition

    题意:给一个区间,分成3个大小不为0的区间,使中间区间的最小值,等于两边区间的最大值。

    题解:首先枚举最左边的区间长度,并求出区间最大值x,可知最右边的区间至少要有一个x定下最右边区间的L的最大合法范围,同时我们知道中间区间不能有小于x的值,所以小于x的值要全给最右边的区间,用线段树二分查出最左边的小于x的值的位置于L的最大合法范围取min,作为最右段的L,再用线段树查询区间最值判断是否合法。

        #include<iostream>
        #include<map>
        using namespace std;
        int t,n,now,p,l,r;
        map<int,int>mp;
        struct madoka{
        	int l;
        	int r;
        	int mi;
        	int mx;
        }ma[2000007];
        void build(int l,int r,int k){
        	ma[k].l=l;
        	ma[k].r=r;
        	if(l==r){
        		scanf("%d",&ma[k].mi);
        		mp[ma[k].mi]=l;
        		ma[k].mx=ma[k].mi;
        		return;
        	}
        	int mid=(l+r)/2;
        	build(l,mid,k*2);
        	build(mid+1,r,k*2+1);
        	ma[k].mi=min(ma[k*2].mi,ma[k*2+1].mi);
        	ma[k].mx=max(ma[k*2].mx,ma[k*2+1].mx);
        	return;
        }
        int qry(int k,int l,int r,int z){
        	if(l<=ma[k].l&&ma[k].r<=r){
        		if(z==1){
        			return ma[k].mx;
        		}
        		else{
        			return ma[k].mi;
        		}
        	}
        	int mid=(ma[k].l+ma[k].r)/2;
        	int ans;
        	if(z)ans=0;
        	else ans=1e9;
        	if(mid>=l){
        		if(z)ans=max(qry(k*2,l,r,z),ans);
        		else ans=min(qry(k*2,l,r,z),ans);
        	}
        	if(mid<r){
        		if(z)ans=max(qry(k*2+1,l,r,z),ans);
        		else ans=min(qry(k*2+1,l,r,z),ans);
        	}
        	return ans;
        }
        int fin(int k,int l,int r){
        	if(ma[k].mi>=now){
        		return 1e9;
        	}
        	if(ma[k].l==ma[k].r){
        		return ma[k].l;
        	}
        	if(l<=ma[k].l&&ma[k].r<=r){
        		if(ma[k*2].mi>=now){
        			return fin(k*2+1,l,r);
        		}
        		else{
        			return fin(k*2,l,r);
        		}
        	}
        	int mid=(ma[k].l+ma[k].r)/2;
        	int mi=1e9;
        	if(mid>=l){
        		mi=min(mi,fin(k*2,l,r));
        	}
        	if(mid<r){
        		mi=min(mi,fin(k*2+1,l,r));
        	}
        	return mi;
        }
        int main(){
        	scanf("%d",&t);
        	while(t--){
        		mp.clear();
        		scanf("%d",&n);
        		build(1,n,1);
        		int a=0,b=0,c=0;
        		for(int i=1;i<=n-2;i++){
        			now=qry(1,1,i,1);
        			l=i+2;
        			r=mp[now];
        			if(l>r){
        				continue;
        			}
        			p=fin(1,l,r);
        			if(p==1e9){
        				p=r;
        			}
        			if(qry(1,i+1,p-1,0)==now&&now==qry(1,p,n,1)){
        				a=i,b=p-i-1,c=n-p+1;
        				break;
        			}
        		}
        		if(a+b+c==n){
        			printf("YES
    ");
        			printf("%d %d %d
    ",a,b,c);
        		}
        		else{
        			printf("NO
    ");
        		}
        		
        	}
        }
    
  • 相关阅读:
    NTC温度检测程序(转)
    基于GPS的经纬度、方位角、距离、航向计算及基于单目视觉的距离计算!
    GPS速度和航向计算(转)
    NOR、 NAND、Raw Flash和 Managed Flash的区别(转)
    FreeModbus V1.6 主机使用说明(转)
    只要单片机具有真正唯一ID,就可以让加密坚不可摧(转)
    Java 给Word添加数字签名
    Java 获取Word中指定图片的坐标位置
    C#/VB.NET 自定义PPT动画路径
    在线编辑Excel——插入图表
  • 原文地址:https://www.cnblogs.com/whitelily/p/14036563.html
Copyright © 2011-2022 走看看