• 钟老头的一键三连


    题:https://www.luogu.com.cn/problem/P3144

    题意:给出n个点m条边的图,逐一删除每个指定点,问每次删除前图是否连通。

    分析:把指定的序列反过来做就行,对于每个加进来的点,看原本集合中有无进来点的连边,有就用并查集联系起来,表示俩者所处连通块连通,(正着切断,反着就判断连通与否就行),每次检查当前集合是否连通即可,复杂度:O(nlogn)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const ll INF=1e18; 
    const int M=3e5+6;
    #define pb push_back
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    int f[M],sz[M],a[M],ans[M];
    set<int>s;
    vector<int>g[M];
    int Find(int x){
        return x==f[x]?x:f[x]=Find(f[x]);
    }
    void unite(int u,int v){
        int x=Find(u),y=Find(v);
        if(x!=y){
            f[y]=x,sz[x]+=sz[y];
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            f[i]=i,sz[i]=1;
        for(int u,v,i=1;i<=m;i++){
            cin>>u>>v;
            g[u].pb(v);
            g[v].pb(u);
        }
        for(int i=1;i<=n;i++)
            cin>>a[i];
        int sign=a[n];
        for(int i=n;i>=1;i--){
            int u=a[i];
            s.insert(u);
            for(auto v : g[u]){
                if(s.count(v))
                    unite(u,v);
            }
        
            if(sz[Find(sign)]==s.size())
                ans[i]=1;
        }
        for(int i=1;i<=n;i++)
            if(ans[i])
                cout<<"YES"<<'
    ';
            else
                cout<<"NO"<<'
    ';
        return 0;
    }
    View Code

     题:https://www.luogu.com.cn/problem/P3146

    题意:给定序列,你能执行这样的操作:当相邻的值是相同的时候就可讲俩者合并成当前值加1,问最大合并出的值是多少

    分析:区间dp,dp[i][j]表示区间[i,j]能合并成的最大值;

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const ll INF=1e18; 
    const int M=300;
    #define pb push_back
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    int dp[M][M];
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0);
        memset(dp,-1,sizeof(dp));
        int n,ans=0;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>dp[i][i],ans=max(ans,dp[i][i]);
        for(int i=1;i<=n;i++){
            for(int j=i-1;j>=1;j--)
                for(int k=j;k<i;k++){
                    if(dp[j][k]==dp[k+1][i]&&dp[j][k]!=-1)
                        dp[j][i]=max(dp[j][i],dp[j][k]+1);
                    ans=max(ans,dp[j][i]);
                }
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

     题:http://acm.hdu.edu.cn/showproblem.php?pid=4623

    题意:找出n的排列中满足相邻相邻互质的个数

    分析:咕咕咕

  • 相关阅读:
    case class inheritance
    [Akka]发送一条消息的内部流程
    Java 8 新特性
    大数据学习笔记
    磁盘结构
    AtomicReference 和 volatile 的区别
    How to support both ipv4 and ipv6 address for JAVA code.
    使用JProfiler分析定位java内存泄露memory leak
    redhat mount iso as one yum repository
    Linux Shell常用技巧
  • 原文地址:https://www.cnblogs.com/starve/p/12399033.html
Copyright © 2020-2023  润新知