20190321杂题选讲解题报告

CF1137C

按照日期把每个博物馆\(i\)拆成\(d\)个点,设\((i,j)\)表示星期\(j\)的第\(i\)个博物馆表示的点,连边:\((i,j)->(to,j\%d+1)\) ,跑一遍\(Tarjan\),再在新图的\(DAG\)\(dp\)即可

#include <bits/stdc++.h>
#define N 5100100
#define rep(i,x,y) for(i=x;i<=y;++i)
using namespace std;

int head[N],H[N],w[N],a[N],b[N],cnt,d;
int dfn[N],low[N],W[N],num[N],st[N],q[N],dp[N],tmp[N],dep,tot,qwq;
bool vis[N],use[N];
char s[55];

struct ed{
    int v,nxt;
}e[N],E[N];

void add(int u,int v){ e[++cnt]=(ed){v,head[u]},head[u]=cnt; }
void ADD(int u,int v){ E[++cnt]=(ed){v,H[u]},H[u]=cnt; }

inline void tarjan(int x){
    dfn[x]=low[x]=++tot;
    vis[x]=1,st[++dep]=x;
    for(int i=head[x];i;i=e[i].nxt){
        int to=e[i].v;
        if(!dfn[to]){
            tarjan(to);
            low[x]=min(low[x],low[to]);
        } else if(vis[to]) low[x]=min(low[x],dfn[to]);
    }
    if(dfn[x]==low[x]){
        qwq++;int qaq=0;
        while(st[dep]!=x){
            num[st[dep]]=qwq,vis[st[dep]]=0;
            if(w[st[dep]] && !use[st[dep]/(d+1)+1]) W[qwq]+=w[st[dep]],use[st[dep]/(d+1)+1]=1,tmp[++qaq]=st[dep]/(d+1)+1;
            st[dep--]=0;
        }
        num[x]=qwq,vis[x]=0;
        if(!use[x/(d+1)+1] && w[x]) W[qwq]+=w[x],use[x/(d+1)+1]=1,tmp[++qaq]=x/(d+1)+1; 
        st[dep--]=0;    
        for(int i=1;i<=qaq;++i) use[tmp[i]]=0;
    }
}

inline void dfs(int x){
    dp[x]=W[x];
    for(int i=H[x];i;i=E[i].nxt){
        int to=E[i].v;
        if(dp[to]==-1) dfs(to);
        dp[x]=max(dp[to]+W[x],dp[x]);
    }
}

int main(){
    int n,m,i,j;
    scanf("%d%d%d",&n,&m,&d);
    rep(i,1,m) scanf("%d%d",&a[i],&b[i]);
    rep(i,1,n){
         scanf("\n%s",s+1);
         rep(j,1,d) w[(i-1)*(d+1)+j]=s[j]-'0';
    }
    rep(i,1,m)
        rep(j,1,d)
            add((a[i]-1)*(d+1)+j,(b[i]-1)*(d+1)+j%d+1);
    rep(i,1,n*(d+1)-1) if(!dfn[i]) tarjan(i);
    cnt=0;
    rep(i,1,n*(d+1)-1)
        for(j=head[i];j;j=e[j].nxt)
            if(num[i]!=num[e[j].v]) ADD(num[i],num[e[j].v]);
    memset(dp,-1,sizeof(dp));
    dfs(num[1]);
    cout<<dp[num[1]];
}

洛谷P1648

套路题

有这样一个显然的性质$\left| a-b \right|\geq a-b $

然后就枚举每一维的符号,正号为1符号为0,表示成一个二进制数,答案为\(max\{ ans[2^i-1-x]+ans[x]\}\)

详见代码

#include <bits/stdc++.h>
#define N 200005
#define lson l,mid,o<<1 
#define rson mid+1,r,o<<1|1
using namespace std;

int x[5],k,p[32],a[32];

int main(){
    int n,mx=0;
    scanf("%d%d",&n,&k);
    memset(p,0xc0,sizeof(p));
    for(int i=1;i<=n;++i){
        for(int j=0;j<k;++j)
            scanf("%d",&x[j]);
        for(int i=0;i<(1<<k);++i){
            a[i]=0;
            for(int j=0;j<k;++j){
                int y=(i>>j)&1;
                if(y) a[i]+=x[j];
                else a[i]-=x[j];
            }           
        }           
        for(int i=0;i<(1<<k);++i) p[i]=max(a[i],p[i]);
    }   
    for(int i=0;i<(1<<k-1);++i) mx=max(p[i]+p[(1<<k)-i-1],mx);
    cout<<mx;
} 

CF618G

我的题= = 貌似被大佬们diss了= =

题解戳这


CF1120D

神仙题啊QAQ

题解戳这

转载于:https://www.cnblogs.com/PsychicBoom/p/10597122.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值