noip2017普及题解

https://www.luogu.org/problemnew/show/3954
https://www.luogu.org/problemnew/show/3955
https://www.luogu.org/problemnew/show/3956
https://www.luogu.org/problemnew/show/3957

T1

甚至不想用c++写

a,b,c=map(int,input().split(' '))
print((a+a+b+b+b+c+c+c+c+c)//10)

T2

乱水

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#define rg register
#define il inline
#define vd void
il int gi(){
    rg int x=0;rg bool flg=0;rg char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')flg=1;ch=getchar();}
    while(isdigit(ch))x=x*10-'0'+ch,ch=getchar();
    return flg?-x:x;
}
int ans[10000001];
il vd checkmn(int&a,int b){if(b<a)a=b;}
int main(){
// 	freopen("librarian.in","r",stdin);
// 	freopen("librarian.out","w",stdout);
    int n=gi(),orz,q=gi();
    for(rg int i=0;i<10000001;++i)ans[i]=19260817;
    while(n--){
        orz=gi();
        checkmn(ans[orz],orz);
        checkmn(ans[orz%10000000],orz);
        checkmn(ans[orz%1000000],orz);
        checkmn(ans[orz%100000],orz);
        checkmn(ans[orz%10000],orz);
        checkmn(ans[orz%1000],orz);
        checkmn(ans[orz%100],orz);
        checkmn(ans[orz%10],orz);
    }
    for(rg int i=0;i<10000001;++i)if(ans[i]==19260817)ans[i]=-1;
    while(q--)gi(),orz=gi(),printf("%d\n",ans[orz]);
    return 0;
}

T3

dij
还有BFS/SPFA/DFS/DP...

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<queue>
#include<cstring>
#define rg register
#define il inline
#define vd void
il int gi(){
    rg int x=0;rg bool flg=0;rg char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')flg=1;ch=getchar();}
    while(isdigit(ch))x=x*10-'0'+ch,ch=getchar();
    return flg?-x:x;
}
const int maxn=101;
int col[maxn][maxn];
struct orzyyb{int x,y;bool col;};
int f[maxn][maxn][2];
bool vis[maxn][maxn][2];
il bool operator <(const orzyyb&a,const orzyyb&b){return f[a.x][a.y][a.col]>f[b.x][b.y][b.col];}
std::priority_queue<orzyyb>que;
const int X[]={0,0,0,1,-1},Y[]={0,1,-1,0,0};
int main(){
// 	freopen("chess.in","r",stdin);
// 	freopen("chess.out","w",stdout);
    int n=gi(),m=gi();
    int x,y,xx,yy,c;
    memset(col,-1,sizeof col);
    memset(f,63,sizeof f);
    while(m--)x=gi(),y=gi(),col[x][y]=gi();
    que.push((orzyyb){1,1,(bool)col[1][1]});
    f[1][1][col[1][1]]=0;
    orzyyb p;
    while(!que.empty()){
        p=que.top();que.pop();
        x=p.x,y=p.y,c=p.col;
        if(vis[x][y][c])continue;
        vis[x][y][c]=1;
        for(rg int i=1;i<5;++i){
            xx=x+X[i],yy=y+Y[i];
            if(xx<1||xx>n||yy<1||yy>n)continue;
            if(~col[xx][yy]){
                if(f[xx][yy][col[xx][yy]]>f[x][y][c]+(c^col[xx][yy])){
                    f[xx][yy][col[xx][yy]]=f[x][y][c]+(c^col[xx][yy]);
                    que.push((orzyyb){xx,yy,(bool)col[xx][yy]});
                }
            }else if(~col[x][y]){
                if(f[xx][yy][0]>f[x][y][c]+(c^0)+2){
                    f[xx][yy][0]=f[x][y][c]+(c^0)+2;
                    que.push((orzyyb){xx,yy,0});
                }
                if(f[xx][yy][1]>f[x][y][c]+(c^1)+2){
                    f[xx][yy][1]=f[x][y][c]+(c^1)+2;
                    que.push((orzyyb){xx,yy,1});
                }				
            }
        }
    }
    int ans=std::min(f[n][n][0],f[n][n][1]);
    if(ans==1061109567)ans=-1;
    printf("%d\n",ans);
    return 0;
}

T4

太套路了

显然答案单调,所以二分k

check用动态规划

一个状态到下一个状态,转移过来的区间会右移(不会左移),所以单调队列优化

套路的死

PS.check加个优化快一倍

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#define rg register
#define il inline
#define vd void
typedef int mainint;
#define int long long
il int gi(){
    rg int x=0;rg bool flg=0;rg char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')flg=1;ch=getchar();}
    while(isdigit(ch))x=x*10-'0'+ch,ch=getchar();
    return flg?-x:x;
}
const int maxn=500010;
int n,x[maxn],s[maxn];
il bool dp(int l,int r,int k){
    --k;
    static int f[maxn],que[maxn];
    int hd=0,tl=0,q=1,ret=-1e18;
    for(rg int i=1;i<=n;++i){
        while(x[i]-x[q]>=l){
            while((hd^tl)&&f[que[tl-1]]<=f[q])--tl;
            que[tl++]=q++;
        }
        while((hd^tl)&&x[i]-x[que[hd]]>r)++hd;
        if(x[i]>=l&&x[i]<=r)f[i]=s[i];
        else f[i]=-1e18;
        if(hd^tl)f[i]=std::max(f[i],f[que[hd]]+s[i]);
        if(f[i]>k)return 0;
    }
    return 1;
}
mainint main(){
// 	freopen("jump.in","r",stdin);
// 	freopen("jump.out","w",stdout);
    n=gi();
    int d=gi(),k=gi();
    for(rg int i=1;i<=n;++i)x[i]=gi(),s[i]=gi();
    if(dp(1,x[n],k)){puts("-1");return 0;}
    int l=0,r=x[n],mid;
    while(l<r){
        mid=(l+r)>>1;
        if(dp(std::max(1ll,d-mid),std::min(d+mid,x[n]),k))l=mid+1;
        else r=mid;
    }
    printf("%lld\n",l);
    return 0;
}
posted @ 2017-11-13 11:16  菜狗xzz  阅读(1145)  评论(2编辑  收藏  举报