[NOIP] 记NOIP2017
来源:互联网 发布:淘宝女包2016新款上市 编辑:程序博客网 时间:2024/05/18 02:16
我好像没什么长进啊
D0
和去年一样在浪
D1
T1一眼不可做,两眼傻逼题?裴蜀定理推一推就是a(b-1)-b
T2大模拟
T3先判零环的情况,然后令
重构一张图,如果
表示度数数组没有清空,被卡了30分啊啊啊啊啊啊啊啊!!!
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <queue>using namespace std;typedef pair<int,int> par;const int N=100010,inf=1<<30;inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void rea(int &x){ char c=nc(); x=0; for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());}int t,n,m,k,p,cnt,G[N];struct iedge{ int t,nx,w;}E[N<<2],iE[N<<2];int iG[N],icnt,rG[N];void iclear(){ memset(iG,0,sizeof(iG)); icnt=0; memset(G,0,sizeof(G)); cnt=0; memset(rG,0,sizeof(rG));}inline void addedge(int x,int y,int z){ E[++cnt].t=y; E[cnt].nx=G[x]; E[cnt].w=z; G[x]=cnt; E[++cnt].t=x; E[cnt].nx=rG[y]; rG[y]=cnt; E[cnt].w=z;}inline void iaddedge(int x,int y){ iE[++icnt].t=y; iE[icnt].nx=iG[x]; iG[x]=icnt;}int dis[N],rdis[N],du[N];priority_queue<par> Q;inline void dij(int s,int *cG,int *cdis){ for(int i=1;i<=n;i++) cdis[i]=inf; cdis[s]=0; Q.push(par(0,s)); while(!Q.empty()){ int x=Q.top().second,y=-Q.top().first; Q.pop(); if(y!=cdis[x]) continue; for(int i=cG[x];i;i=E[i].nx) if(cdis[E[i].t]>cdis[x]+E[i].w){ cdis[E[i].t]=cdis[x]+E[i].w; Q.push(par(-cdis[E[i].t],E[i].t)); } }}int vis[N],low[N],dfn[N],sta[N],tp,tms,imx;void tarjan(int x){ low[x]=dfn[x]=++tms; vis[x]=1; sta[++tp]=x; for(int i=iG[x];i;i=iE[i].nx){ if(!vis[iE[i].t]) tarjan(iE[i].t); if(vis[iE[i].t]==1) low[x]=min(low[x],low[iE[i].t]); } if(low[x]==dfn[x]){ int cura=inf,curb=inf,cur,ccnt=0; while(1){ cur=sta[tp--]; vis[cur]=2; ccnt++; cura=min(cura,dis[cur]); curb=min(curb,rdis[cur]); if(cur==x || !tp) break; } if(ccnt>1) imx=min(imx,cura+curb); }}inline bool nooo(){ dij(n,rG,rdis); for(int i=1;i<=n;i++) vis[i]=low[i]=dfn[i]=0; tms=tp=0; imx=inf; for(int i=1;i<=n;i++) if(!vis[i]) tarjan(i); return imx<=dis[n]+k;}int f[N][55];int q[N],l,r;int main(){ rea(t); while(t--){ iclear(); rea(n); rea(m); rea(k); rea(p); for(int i=1,x,y,z;i<=m;i++){ rea(x); rea(y); rea(z); addedge(x,y,z); if(z==0) iaddedge(x,y); } dij(1,G,dis); if(nooo()){ puts("-1"); continue; } for(int i=1;i<=n;i++) for(int j=0;j<=k;j++){ if(dis[i]+j+rdis[i]>dis[n]+k) break; f[i][j]=0; } for(int i=1;i<=n;i++) du[i]=0; for(int x=1;x<=n;x++) for(int i=G[x];i;i=E[i].nx) if(dis[E[i].t]==dis[x]+E[i].w) du[E[i].t]++; l=1; r=0; q[r=1]=1; while(l<=r){ int x=q[l++]; for(int i=G[x];i;i=E[i].nx) if(dis[E[i].t]==dis[x]+E[i].w){ du[E[i].t]--; if(!du[E[i].t]) q[++r]=E[i].t; } } f[1][0]=1; for(int j=0;j<=k;j++){ for(int ii=1;ii<=r;ii++){ int x=q[ii]; int cur=f[x][j]; if(!cur || dis[x]+j+rdis[x]>dis[n]+k) continue; for(int i=G[x];i;i=E[i].nx){ int dd=dis[x]+j+E[i].w-dis[E[i].t]; if(dd<=k) f[E[i].t][dd]=(f[E[i].t][dd]+f[x][j])%p; } } } int ans=0; for(int i=0;i<=k;i++) ans=(ans+f[n][i])%p; printf("%d\n",ans); } return 0;}
D1就这样吧…
D2
T1并查集送分
T2好像写了个三进制的状压DP,复杂度是
按层DP,
令三进制状态
数组开小-10
#include <cstdio>#include <iostream>#include <algorithm>using namespace std;int n,m;int lk[15][15],pw[15],val[15];int f[15][531445];int ttt[531445],lst[4150],ttt1[4150],sz[531445];inline int iinn(int x,int y){ return (x/pw[y-1])%3;}inline int cst(int S){ int ret=0; for(;S;S-=(1<<(lst[S]-1))){ if(val[lst[S]]==(1<<30)) return 1<<30; ret+=val[lst[S]]; } return ret;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) lk[i][j]=1<<30; for(int i=1,x,y,z;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); lk[x][y]=lk[y][x]=min(lk[x][y],z); } pw[0]=1; for(int i=1;i<=n;i++) pw[i]=3*pw[i-1]; for(int i=1;i<=n;i++) for(int j=0;j<pw[n];j++) f[i][j]=1<<30; for(int i=0;i<pw[n];i++) for(int j=1;j<=n;j++) if(!iinn(i,j)) ttt[i]|=1<<(j-1); else sz[i]++; for(int i=1;i<(1<<n);i++) for(int j=1;j<=n;j++) if((i>>(j-1))&1) ttt1[i]+=pw[j-1]*2; lst[1]=1; for(int i=2;i<(1<<n);i++) lst[i]=lst[i>>1]+1; for(int i=1;i<=n;i++) f[1][pw[i-1]*2]=0; int ans=1<<30; for(int i=1;i<=n;i++) for(int S=0;S<pw[n];S++){ if(f[i][S]>=ans) continue; if(sz[S]==n) ans=min(ans,f[i][S]); for(int j=1;j<=n;j++) if(!iinn(S,j)){ val[j]=1<<30; for(int k=1;k<=n;k++) if(iinn(S,k)==2) val[j]=min(val[j],lk[k][j]); } int nxt=0,SS=ttt[S]; for(int j=1;j<=n;j++) if(iinn(S,j)) nxt+=pw[j-1]; for(int ss=SS;ss;ss=(ss-1)&SS){ int cur=cst(ss); if(cur==(1<<30)) continue; f[i+1][nxt+ttt1[ss]]=min(f[i+1][nxt+ttt1[ss]],f[i][S]+cur*i); } } printf("%d\n",ans); return 0;}
T3我是个傻逼啊
暴力打挂,没开longlong,-30
大力平衡树模拟就好了…
#include <cstdio>#include <iostream>#include <algorithm>#include <cstdlib>#define fi first#define se secondusing namespace std;typedef long long ll;const int N=2000010;struct node{ node *ls,*rs; int x,y,val,size,key,tag;}pool[N],*t;int n,m,q;inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){ char c=nc(); x=0; for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());}node *ro[N],*L;inline node *crt(int x,int y,int k,int v){ node *ret=t++; ret->x=x; ret->y=y; ret->val=v; ret->key=k; return ret;}inline void Up(node *x){ x->size=(x->ls?x->ls->size:0)+(x->rs?x->rs->size:0)+1;}inline void Push(node *x){ if(!x->tag) return ; if(x->ls) x->ls->tag+=x->tag,x->ls->key+=x->tag; if(x->rs) x->rs->tag+=x->tag,x->rs->key+=x->tag; x->tag=0;}inline node *Merge(node *x,node *y){ if(!x || !y) return x?x:y; Push(x); Push(y); if(x->val>y->val){ x->rs=Merge(x->rs,y); Up(x); return x; } else{ y->ls=Merge(x,y->ls); Up(y); return y; }}void PutAns(ll x){ if(x>=10) PutAns(x/10); putchar(x%10+'0');}typedef pair<node*,node*> Dnode;Dnode Split(node *cur,int x){ if(!cur) return Dnode(NULL,NULL); Push(cur); Dnode ret; if(cur->key<x){ ret=Split(cur->rs,x); cur->rs=ret.fi; ret.fi=cur; } else{ ret=Split(cur->ls,x); cur->ls=ret.se; ret.se=cur; } Up(cur); return ret;}inline node *lst(node *cur){ while(cur->rs) cur=cur->rs; return cur;}inline node *fst(node *cur){ while(cur->ls) cur=cur->ls; return cur;}int main(){ t=pool; read(n); read(m); read(q); for(int i=1;i<=n;i++) L=Merge(L,crt(i,m,i,rand())); for(int i=1;i<=n;i++) ro[i]=Merge(ro[i],crt(i,1,1,rand())); while(q--){ int x,y; read(x); read(y); if(y==m){ Dnode A=Split(L,x),B=Split(A.se,x+1); PutAns(1LL*(B.fi->x-1)*m+B.fi->y); putchar('\n'); B.fi->key=n; if(B.se) B.se->tag-=1,B.se->key-=1; L=Merge(A.fi,Merge(B.se,B.fi)); } else{ Dnode A=Split(ro[x],y),B=Split(A.se,y+1); node *cur; if(B.fi) cur=B.fi; else cur=lst(A.fi); PutAns(1LL*(cur->x-1)*m+cur->y+y-cur->key); putchar('\n'); if((!B.se || fst(B.se)->key!=y+1) && y+1!=m) B.se=Merge(crt(cur->x,cur->y+y-cur->key+1,y+1,rand()),B.se); if(B.se) B.se->tag-=1,B.se->key-=1; ro[x]=Merge(A.fi,B.se); Dnode C=Split(L,x),D=Split(C.se,x+1); D.fi->key=m-1; if(D.se) D.se->tag-=1,D.se->key-=1; ro[x]=Merge(ro[x],D.fi); if(cur->key==y) cur->key=n,L=Merge(C.fi,Merge(D.se,cur)); else L=Merge(C.fi,Merge(D.se,crt(cur->x,cur->y+y-cur->key,n,rand()))); } } return 0;}
分数跟去年一样490
D1T3+D2T2+D2T3=30+10+30=70
因为自己傻逼少了70分
怕是要退役了
阅读全文
1 0
- [NOIP] 记NOIP2017
- NOIp2017游记 & 再见NOIP
- 【NOIP】一篇正式的NOIP2017总结
- NOIP模拟9.16(TYVJ NOIP2017模拟赛D1)
- NOIP模拟9.17(TYVJ NOIP2017模拟赛D2)
- NOIP模拟9.23(TYVJ NOIP2017模拟赛D1)
- NOIP 模板整理计划 NOIP2017 RP++(持续更新中~)
- NOIP2017 初赛划水记
- noip2017退役记
- NOIP2017复赛爆炸记
- NOIP2017翻车记
- NOIP2017 Orz记
- NOIP2017 爆炸记
- Noip2017丢人记
- NOIp2017酱油记
- NOIP2017退役记
- NOIP2017 睡觉记
- noip2017退役记
- Leetcode 70. Climbing Stairs
- 关于断点续传和greendao一起使用
- 代理ip的爬虫实现
- 云计算时代的进阶者,专访景安董事长杨小龙
- 使用JSP+Servlet+Jdbc+Echatrs实现对豆瓣电影Top250的展示
- [NOIP] 记NOIP2017
- restful最佳实践--接口规范
- 【JS】观察者模式
- aframe.js 结合 gamepad api 游戏手柄摇杆移动摄像机实验
- 【Scikit-Learn 中文文档】内核岭回归
- 绘制气泡
- Java-003-第一个程序及class与java
- Java中的synchronized
- 系统架构