钟老头的一键三连

题: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"<<'\n';
        else
            cout<<"NO"<<'\n';
    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的排列中满足相邻相邻互质的个数

分析:咕咕咕

posted @ 2020-03-02 23:45  starve_to_death  阅读(123)  评论(0编辑  收藏  举报