noip2017普及题解
2017-11-13 11:16
218 查看
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
还有BFS/SPFA/DFS/DP...
显然答案单调,所以二分k
check用动态规划
一个状态到下一个状态,转移过来的区间会右移(不会左移),所以单调队列优化
套路的死
PS.check加个优化快一倍
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 [0],f [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 ,k)){puts("-1");return 0;} int l=0,r=x ,mid; while(l<r){ mid=(l+r)>>1; if(dp(std::max(1ll,d-mid),std::min(d+mid,x ),k))l=mid+1; else r=mid; } printf("%lld\n",l); return 0; }
相关文章推荐
- 2017NOIp 普及组第二题 图书管理员
- NOIP 2017 普及组 棋盘
- [NOIP2017普及组]棋盘
- NOIP2017普及组解题报告
- 2017NOIP普及模拟赛题解报告
- NOIP2017成绩(普及T1)
- NOIP2017普及组复赛解题报告
- 2017NOIP普及组 赛前心得
- NOIP2017普及组比赛总结
- NOIP 2017 普及组 图书馆员
- NOIP普及组2017比赛总结
- NOIP2017普及组题解
- Noip2017普及组T4 跳房子 二分答案 单调队列
- 【NOIP 2017普及组】 成绩
- NOIP2017普及组翻车记
- [NOIP2017普及组]T2图书管理员(前导0)
- ◆竞赛题目◆◇NOIP 2017 普及组◇ 图书管理员
- 【NOIP2017普及组正式赛】成绩
- 【NOIP 2017普及组】 图书管理员
- 【NOIP2017普及组】棋盘