2017.10.26离线赛总结

magic ——4124

思路:强模拟,不解释…

message ——4125

思路:仔细读完题,实际上是找一个最小的环,那么便bfs,但这样只有60,
因为n<=200 000,也便知道只有O(n log n)的复杂度,而且,此题的关系比较明显——父子关系,脑海一闪而过——并查集,再思考一下,并两个集合,查一数,十分符合。

#include<bits/stdc++.h>
#define REP(i,f,t ) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t ) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define INF 0x3f3f3f3f
#define N 200005
using namespace std;
int n;
vector<int>E[N];
bool vis[N];
struct p100{
    int ans;
    int D[N],fa[N],nxt[N];
    int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}
    void merege(int x,int y){
        int fx=Find(x);
        int fy=Find(y);
        fa[fx]=fy;
    }
    void dfs(int x,int dep){
        vis[x]=1;
        D[x]=dep;
        if(!vis[nxt[x]])dfs(nxt[x],dep+1);
        else {
            int sum=D[x]-D[nxt[x]]+1;
            ans=min(ans,sum);
        }
    }
    void solve(){
        ans=INF;
        REP(i,1,n)fa[i]=i;
        REP(i,1,n){
            int x;scanf("%d",&x);nxt[i]=x;
            if(Find(x)!=Find(i))merege(i,x);
            else {
                memset(vis,0,sizeof(vis));
                dfs(i,0);
            }
        }
        cout<<ans<<endl;
    }
}p100;
int main(){
//  freopen("message.in","r",stdin);
//  freopen("message.out","w",stdout);
    cin>>n;
    p100.solve();
}

landlords ——4126

思路:爆搜…(还是要考虑周到,再敲代码),也就这么几种特殊情况:单顺子,双顺子,三顺子,三带一或二,四不带,四带二单或一对。而这看起来挺多,但再次分类一下,单顺,双顺,三顺,三带,四带。

#include<bits/stdc++.h>
#define REP(i,f,t ) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t ) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define INF 0x3f3f3f3f
#define N 30
using namespace std;
int T,n,x,y,ans;
int mark[N];
void Init(){
    memset(mark,0,sizeof(mark));
    ans=0;
}
bool check(){
    REP(i,1,15)
        if (mark[i]) return 0;
    return 1;
}
void dfs(int cnt){
    if(cnt>ans)return;
    if (check()) {
        ans=min(ans,cnt);
        return;
    }
    int sum=0;
    REP(i,1,13)if(mark[i])sum++;
    if(mark[14]+mark[15])sum++;
    ans=min(ans,cnt+sum);
    REP(l,1,5){
        if (l==1){// single shunzi
            REP(i,1,8)
                if (mark[i]) {
                    bool flag=1;
                    for (int j=i+1; j<=i+3; ++j)
                        if (!mark[j]) {
                            flag=0;
                            break;
                        }
                    if (!flag) continue;
                    for (int j=i+4; j<13&&mark[j]; ++j) {
                        for (int k=i; k<=j; ++k) --mark[k];
                        dfs(cnt+1);
                        for (int k=i; k<=j; ++k) ++mark[k];
                    }
                }
        }
        if (l==2) {//double shunzi
            REP(i,1,10)
                if (mark[i]>=2&&mark[i+1]>=2)
                    for (int j=i+2; j<13&&mark[j]>=2; ++j) {
                        for (int k=i; k<=j; ++k) mark[k]-=2;
                        dfs(cnt+1);
                        for (int k=i; k<=j; ++k) mark[k]+=2;
                    }
        }
        if (l==3) {//triple shunzi
            REP(i,1,11)
                if (mark[i]>=3) {
                    if (mark[i+1]<3) continue;
                    for (int j=i; j<13&&mark[j]>=3; ++j) {
                        for (int k=i; k<=j; ++k) mark[k]-=3;
                        dfs(cnt+1);
                        for (int k=i; k<=j; ++k) mark[k]+=3;
                    }
                }
        }

        if (l==4) {//san dai
            REP(i,1,13)
                if (mark[i]>=3) {
                    mark[i]-=3;
                    REP(j,1,15)
                        if (mark[j]) {
                            --mark[j];
                            dfs(cnt+1);
                            ++mark[j];
                        }
                    REP(j,1,15)
                        if (mark[j]>=2) {
                            mark[j]-=2;
                            dfs(cnt+1);
                            mark[j]+=2;
                        }
                    mark[i]+=3;
                }

        }
        if (l==5) {//si dai

            REP(i,1,15)
                if (mark[i]>=4) {
                    mark[i]-=4;
                    REP(j,1,15)
                        if (mark[j]) {
                            --mark[j];
                            REP(k,j,15)
                                if (mark[k]) {
                                    --mark[k];
                                    dfs(cnt+1);
                                    ++mark[k];
                                }
                            ++mark[j];
                        }
                    mark[i]+=4;
                }
            REP(i,1,15)
                if (mark[i]>=4) {
                    mark[i]-=4;
                    REP(j,1,15)
                        if (mark[j]>=2) {
                            mark[j]-=2;
                            REP(k,j,15)
                                if (mark[k]>=2) {
                                    mark[k]-=2;
                                    dfs(cnt+1);
                                    mark[k]+=2;
                                }
                            mark[j]+=2;
                        }
                    mark[i]+=4;
                }
        }
    }
}
int main() {
    scanf("%d%d",&T,&n);
    while (T--){
        Init();
        REP(i,1,n){
            scanf("%d%d",&x,&y);
            if (!x) mark[y+13]++;
            if (x==1||x==2) mark[x+11]++;
            if (x>=3) mark[x-2]++;
        }
        REP(i,1,13)if(mark[i])ans++;
        if(mark[14]+mark[15])ans++;
        dfs(0);
        printf("%d\n",ans);
    }
}

小结:今天的最后一题还是敲地太乱了,没怎么想好久开始敲,结果连爆搜都敲不出来——深思熟虑后再动键盘…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值