2019年7月30日(NOIP模拟赛DAY2)

T3线段树写挂,郁闷~!!!~  

prob1:野区(buff)  

题目大意:同2019.7.23的\(T3\)盛宴(\(party\))  

\(WoCao\),原题写挂,不想说什么了

原题就不讲思路了,直接上代码(以后要注意分类的全面):

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define int long long
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
const int xx=4010;
int dis[xx][xx],vis[xx],que[xx];
int head[xx],nxt[xx<<1],to[xx<<1],cnt=0;
inline void add(int u,int v){nxt[++cnt]=head[u];to[cnt]=v;head[u]=cnt;}
inline void bfs(int g)
{
    dis[g][g]=0;
    vis[g]=g;
    int hd=0,tl=-1;
    que[++tl]=g;
    while(hd<=tl)
    {
        int gg=que[hd++];
        for(int j=head[gg];j;j=nxt[j])
        {
            int jj=to[j];
            if(vis[jj]!=g)
            {
                vis[jj]=g;
                dis[g][jj]=dis[g][gg]+1;
                que[++tl]=jj;
            }
        }
    }
}
signed main()
{
    int n=in,m=in;
    fur(i,1,m)
    {
        int x=in,y=in;
        add(x,y);
        add(y,x);
    }
    memset(dis,0x7f,sizeof(dis));
    fur(i,1,n) bfs(i);
    int s1=in,t1=in,p1=in;
    int s2=in,t2=in,p2=in;
    if(dis[s1][t1]>p1||dis[s2][t2]>p2)
    {
        printf("-1\n");
        return 0;
    }
    int ans=dis[s1][t1]+dis[s2][t2];
    fur(i,1,n) fur(j,1,n)
    {
        if(dis[s1][i]+dis[i][j]+dis[j][t1]<=p1&&dis[s2][i]+dis[i][j]+dis[j][t2]<=p2) ans=min(ans,dis[s1][i]+dis[s2][i]+dis[i][j]+dis[j][t1]+dis[j][t2]);
        if(dis[s1][j]+dis[j][i]+dis[i][t1]<=p1&&dis[s2][i]+dis[i][j]+dis[j][t2]<=p2) ans=min(ans,dis[s1][j]+dis[s2][i]+dis[j][i]+dis[i][t1]+dis[j][t2]);
    }
    printf("%lld\n",m-ans);
    return 0;
}

prob3:云顶之奕(cloud)

题目大意:已知\(n\)个二元组\((a_i,b_i)\),与定值\(w\),有两个变量\(p,q\),当有\(m_1\)个二元组满足\(b_i<=q\)时,对答案有\(m_1*q*w\)的贡献,而若其他二元组中有\(m_2\)个二元组满足\(a_i<=p\),将对答案有\(m_2*p\)的贡献,求当\(q\)分别等于\(1\)\(max(b_i)+1\)时,答案的最大值

50分强力部分分:用桶排与链表维护二元组,用值域线段树维护答案,\(O(logn-n)\)地修改:  

#include<bits/stdc++.h>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define int long long
inline int read()
{
    int x=0;
    char ch=getchar();
    for(;!isalnum(ch);ch=getchar());
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
const int xx=1e5+10;
struct linetree
{
    int sz,ans;
    linetree *son[2];
    linetree():sz(0),ans(0)
        {
            son[0]=son[1]=NULL;
        }
};
linetree *root,*ty,pool[xx<<2];
int res[xx],n,w,head[xx],nxt[xx],a[xx],wuhan[xx],mx=0,alll;
inline linetree *newlt()
{
    *++ty=linetree();
    return ty;
}
inline void up(linetree *k)
{
    k->ans=0;
    if(k->son[0]) k->ans=max(k->ans,k->son[0]->ans);
    if(k->son[1]) k->ans=max(k->ans,k->son[1]->ans);
}
inline void add(linetree *k,int l,int r,int c)
{
    ++k->sz;
    if(l==r)
    {
        k->ans=k->sz*wuhan[l];
        return;
    }
    int mid=(l+r)>>1;
    if(!k->son[0]) k->son[0]=newlt();
    add(k->son[0],l,mid,c);
    if(c>mid)
    {
        if(!k->son[1]) k->son[1]=newlt();
        add(k->son[1],mid+1,r,c);
        up(k);
    }
    else k->ans=max(k->son[0]->ans,k->ans);
}
inline void ade(int u,int v)
{
    nxt[v]=head[u];
    head[u]=v;
}
inline void sol()
{
    int all=n;
    fur(c,1,mx)
    {
        for(int j=head[c-1];j;j=nxt[j])
        {
            add(root,1,alll,a[j]);
            --all;
        }
        res[c]=all*c*w+root->ans;
    }
}
signed main()
{
    n=in;w=in;
    fur(i,1,n)
    {
        wuhan[i]=a[i]=in;
        int y=in;
        ade(y,i);
        mx=max(mx,y);
    }
    sort(wuhan+1,wuhan+n+1);
    alll=unique(wuhan+1,wuhan+n+1)-wuhan-1;
    fur(i,1,n) a[i]=lower_bound(wuhan+1,wuhan+alll+1,a[i])-wuhan;
    ++mx;
    ty=pool;
    root=newlt();
    sol();
    fur(i,1,mx) printf("%lld ",res[i]);printf("\n");
    return 0;
}

正解:分块+斜率优化(自己推柿子)

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define fdr(i,a,b) for(int i=a;i>=b;--i)
#define int long long
#define jiba signed
#define K(j,i) (double)(d[i]-d[j])/(j-i)
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
const int xx=1e5+10;
const int yy=1e3+10;
int pos[xx],d[xx],cnt[xx],tp=0,mx=0;
int que[yy][yy],ls[yy],rs[yy],tag[yy],ans[yy],hd[yy],tl[yy];
int res[xx],n,w,a[xx],head[xx],nxt[xx];
inline int get(int k,int i){return tag[k]*i+d[i];}
inline void add(int u,int to){nxt[to]=head[u];head[u]=to;}
inline void build(int k)
{
    d[rs[k]]=rs[k]*cnt[rs[k]];
    fdr(i,rs[k]-1,ls[k]) d[i]=(d[i+1]/(i+1)+cnt[i])*i;
    hd[k]=1,tl[k]=1;
    fur(i,ls[k],rs[k])
    {
        while(K(i,que[k][tl[k]])<K(que[k][tl[k]],que[k][tl[k]-1])&&tl[k]>hd[k]) --tl[k];
        que[k][++tl[k]]=i;
    }
    while(get(k,que[k][hd[k]])<get(k,que[k][hd[k]+1])&&hd[k]<tl[k]) hd[k]++;
    ans[k]=get(k,que[k][hd[k]]);
}
inline void ad_tag(int k)
{
    while(get(k,que[k][hd[k]])<get(k,que[k][hd[k]+1])&&hd[k]<tl[k]) hd[k]++;
    ans[k]=get(k,que[k][hd[k]]);
}
inline void sol()
{
    int all=n;
    fur(i,1,tp)
    {
        for(int j=head[i-1];j;j=nxt[j])
        {
            --all;
            ++cnt[a[j]];
            fur(k,1,pos[a[j]]-1) ++tag[k],ad_tag(k);
            build(pos[a[j]]);
        }
        fur(j,1,pos[mx]) res[i]=max(res[i],ans[j]);
        res[i]+=all*w*i;
    }
}
jiba main()
{
    n=in;w=in;
    fur(i,1,n)
    {
        a[i]=in;
        mx=max(mx,a[i]);
        int y=in;
        tp=max(tp,y);
        add(y,i);
    }
    int tmp=sqrt(mx);
    fur(i,1,mx)
    {
        pos[i]=(i-1)/tmp+1;
        if(pos[i]!=pos[i-1]) ls[pos[i]]=i;
        rs[pos[i]]=i;
    }
    tp++;
    sol();
    fur(i,1,tp) printf("%lld ",res[i]);printf("\n");
    return 0;
}

prob2:跑得快(\(pdk\))

题目大意:斗地主(改),可单打,对子,三带二,炸弹(不算步数),顺子,双顺子,三顺子,求最小步

正解\(DP\)+部分搜索,\(DP\)预处理单打,对子,三带二的情况,爆搜各种顺子

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define fdr(i,a,b) for(int i=a;i>=b;--i)
#define int long long
#define jiba signed
inline int read()
{
    int x=0,f=1;char ch=getchar();
    for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
int n,ans;
int f[7][9][13][25],cnt[14],upstair[14]={0,4,4,4,4,4,4,4,4,4,4,4,3,1};
inline void up(int &a,int b){a=a>b?b:a;}
inline void init()
{
    fur(i,0,n/4+1) fur(j,0,n/3+1) fur(k,0,n/2+1) fur(l,0,n+1) if(i*4+j*3+k*2+l<=n)
    {
        if(i)
        {
            up(f[i][j][k][l],f[i-1][j][k][l]);
            up(f[i][j][k][l],f[i-1][j+1][k][l+1]);
            up(f[i][j][k][l],f[i-1][j][k+2][l]);
            up(f[i][j][k][l],f[i-1][j][k][l+4]);
        }
        if(j)
        {
            up(f[i][j][k][l],f[i][j-1][k][l]+1);
            if(k) up(f[i][j][k][l],f[i][j-1][k-1][l]+1);
            if(l) up(f[i][j][k][l],f[i][j-1][k][l-1]+1);
            if(l>=2) up(f[i][j][k][l],f[i][j-1][k][l-2]+1);
            up(f[i][j][k][l],f[i][j-1][k+1][l+1]);
            up(f[i][j][k][l],f[i][j-1][k][l+3]);
        }
        if(k)
        {
            up(f[i][j][k][l],f[i][j][k-1][l]+1);
            up(f[i][j][k][l],f[i][j][k-1][l+2]);
        }
        if(l) up(f[i][j][k][l],f[i][j][k][l-1]+1);
    }
}
inline void search(int w,int las)
{
    if(w>=ans) return;
    if(las==0) return;
    int rest[5]={0,0,0,0,0};
    fur(i,1,13) if(cnt[i]) rest[cnt[i]]++;
    up(ans,w+f[rest[4]][rest[3]][rest[2]][rest[1]]);
    fur(i,1,11)
    {
        if(cnt[i]>=3)
        {
            cnt[i]-=3;
            int j=i+1;
            while(j<=12&&cnt[j]>=3)
            {
                cnt[j]-=3;
                search(w+1,las-(j-i+1)*3);
                ++j;
            }
            fur(q,i,j-1) cnt[q]+=3;
        }
    }
    fur(i,1,10)
    {
        if(cnt[i]>=2&&cnt[i+1]>=2)
        {
            cnt[i]-=2;
            cnt[i+1]-=2;
            int j=i+2;
            while(j<=12&&cnt[j]>=2)
            {
                cnt[j]-=2;
                search(w+1,las-(j-i+1)*2);
                ++j;
            }
            fur(q,i,j-1) cnt[q]+=2;
        }
    }
    fur(i,1,8)
    {
        if(cnt[i]&&cnt[i+1]&&cnt[i+2]&&cnt[i+3])
        {
            cnt[i]-=1;
            cnt[i+1]-=1;
            cnt[i+2]-=1;
            cnt[i+3]-=1;
            int j=i+4;
            while(j<=12&&cnt[j])
            {
                cnt[j]-=1;
                search(w+1,las-(j-i+1));
                ++j;
            }
            fur(q,i,j-1) cnt[q]+=1;
        }
    }
}
jiba main()
{
    freopen("pdk.in","r",stdin);
    freopen("pdk.out","w",stdout);
    int t=in;n=in+1;
    memset(f,0x3f,sizeof(f));
    f[0][0][0][1]=0;
    init();
    while(t--)
    {
        memset(cnt,0,sizeof(cnt));
        ans=23;
        fur(i,1,n-1)
        {
            int x=in,y=in;
            if(x==1) cnt[12]++;
            else if(x==2) cnt[13]++;
            else cnt[x-2]++;
        }
        fur(i,1,12)
        {
            if(cnt[i]<upstair[i])
            {
                ++cnt[i];
                search(0,n);
                --cnt[i];
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ALANALLEN21LOVE28/p/11312998.html
今日推荐