zoukankan      html  css  js  c++  java
  • 2020-2021 ACM-ICPC, Asia Seoul Regional Contest 部分题目解答

    传送门
    https://codeforces.com/gym/102920

    B

    签到

    C

    题意:给出n个点,其中k个是特殊点,求有多少个点在特殊点两两连接的路径之间(特殊点自身也算)。
    分析:简单的树形DP。
    对于一个结点u,它被计入贡献当且仅当下面的条件中存在一条或多条满足:

    • 它的两棵子树上都有特殊点
    • 它的父节点有特殊点子节点有特殊点
    • 它本身是特殊点
    代码
    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    const int N=1e5+5;
    struct node{
    	int to,next;
    }e[N<<1];
    int head[N],tot;
    void add(int u,int v){e[tot].to=v;e[tot].next=head[u];head[u]=tot++;}
    
    bool tag[N];
    int n,k;
    int ans=0;
    
    int dfs(int u,int fa){
    	 int res=0;
    	 if(tag[u]) res++;
    	 
    	 int cnt=0;
    	 for(int i=head[u];~i;i=e[i].next){
    	 	int go=e[i].to;
    	 	if(go==fa) continue;
    	 	int w=dfs(go,u);
    	 	if(w) cnt++;
    	 	res+=w;
    	 }
    	 if(res && res<=k-1 || tag[u] || cnt>=2) ans++;
    	 return res;
    }
    
    int main(){
    	memset(head,-1,sizeof head);
    	cin>>n>>k;
    	FOR(i,1,n-1){
    		int u,v,w; cin>>u>>v>>w;
    		add(u,v); add(v,u);
    	}	
    	
    	FOR(i,1,k){
    		int u; cin>>u;
    		tag[u]=1;
    	}
    
    	dfs(1,-1);
    	
    	cout<<ans<<endl;
    	
        return 0;
    }
    

    E

    分析:递推
    从最后一项开始分析,可以知道,最后一项只可能是0,1,而最后一项为1时,就是题目中的computer出了错误,我们可以对这个错误进行修正,那么
    需要修改的就是最后一项的前一项了。

    如何进行修正呢?

    修正意味着i与另一个数的胜负由它们的大小关系决定
    首先,我们考察项i:
    可知对于i,能够产生大小判断波动大只有i-1,i+1,故在这里只需考察i及i-1(因为i与i+1已经修正过了)(方便起见,我们将i比旁边的数记为,i比旁边的数记为
    i的胜场可以是0,1
    而胜场的差(f值)也可以是0,1

    具体修正方案:

    我们约定(x,y)意味着i的前后两次胜负情况,比如(0,1)的意思是有一次i胜了0场,有一次胜了1场

    而i+1项为1时(即f[i+1]=1,同时我们知道这意味着i项已经胜了一场),对此进行分类讨论:

    • f[i]=1时,i的两次胜负情况可能为(0,1) 因此在修正之后变为(0,0)
    • f[i]=0时,i的两次胜负情况可能为(1,1) 因此在修正之后变为(1,0)
    代码
    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    const int N=1e6+5;
    int f[N];
    int n;
    
    int main(){
    	cin>>n;
    	FOR(i,1,n) cin>>f[i];
    	
    	bool ok=1;
    	DWN(i,n,1){
    		if(f[i]>=2 || f[i]<0){
    			ok=0;
    			break;
    		}
    		
    		if(f[i]==1) f[i-1]=(f[i-1]==0?1:f[i-1]-1);
    	}
    	
    	if(ok && !f[1]) puts("YES");
    	else puts("NO");
        return 0;
    }
    

    L

    题意:给定一个数组,求 (max((a[i]+a[j])(j-i)))
    分析:决策单调性分治

    代码
    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int N=1e6+5;
    ll a[N];
    int n;
    
    int A1[N],A2[N];
    ll ans=-1;
    
    ll cal(int p1,int p2){
    	ll res=(A2[p2]-A1[p1])*(a[A2[p2]]+a[A1[p1]]);
    	return res;	
    }
    
    void solve(int l1,int r1,int l2,int r2){
    	if(l1>r1) return;
    	int mid=l1+r1>>1;
    	int pos=l2;
    	FOR(i,l2+1,r2)
    		if(cal(mid,pos)<cal(mid,i)) pos=i;
    	ans=ans>cal(mid,pos)?ans:cal(mid,pos);
    	solve(l1,mid-1,pos,r2); solve(mid+1,r1,l2,pos);
    }
    
    int main(){
    	cin>>n;
    	FOR(i,1,n) a[i]=read();
    	
    	int cnt1=0,cnt2=0;
    	A1[++cnt1]=1; A2[++cnt2]=n;
    	FOR(i,2,n)
    		if(a[i]>a[A1[cnt1]]) A1[++cnt1]=i;
    	DWN(i,n-1,1)
    		if(a[i]>a[A2[cnt2]]) A2[++cnt2]=i;
    	solve(1,cnt1,1,cnt2);
    	
    	cout<<ans<<endl;
    	
        return 0;
    }
    
    /* 
    加了快读 109 ms	15700 KB 
    不加TLE orz
    */
    
  • 相关阅读:
    Linux学习笔记之Linux Centos关闭防火墙
    ELK学习笔记之Logstash详解
    ELK学习笔记之ElasticSearch的索引详解
    C语言拼接字符串 -- 使用strcat()函数
    linux 中的 open() read() write() close() 函数
    stderr 和stdout
    ubuntu14.04 放开串口权限
    ubuntu14.04 安装 openssh-server
    串口接线
    ubuntu + usb转RS232驱动
  • 原文地址:https://www.cnblogs.com/Tenshi/p/14447855.html
Copyright © 2011-2022 走看看