2018.7.3模擬賽
阿新 • • 發佈:2018-07-03
樹形背包 lib 操作 r+ bool lse 裸題 stdout host
我真的是菜的一筆
T1:
一道貪心大水題,然後我wa了。。。
就是把它按照結束時間排個序,然後亂搞一下就行了
#include <cstdio> #include <cstdlib> #include <algorithm> int n,ans; struct Node{int t,s,k;} r[100005]; bool cmp(Node x,Node y){if(x.s!=y.s) return x.s<y.s;return x.k<y.k;} int main(){ // freopen("manage.in","r",stdin); // freopen("manage.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&r[i].t,&r[i].s),r[i].k=r[i].s-r[i].t; std::sort(r+1,r+1+n,cmp); ans=0; int mn=0x3f3f3f3f; for(int i=1;i<=n;i++){ ans+=r[i].t; if(ans>r[i].s) {puts("-1");return 0;} mn=std::min(mn,r[i].s-ans); } if(mn<0) puts("-1"); }
T2
縮點+樹形背包,縮完點就和選課一樣了。
tarjan寫挫,dp寫挫。
口胡AC,手寫10分GG
#include <cstdio> #include <vector> #include <algorithm> #include <cstdlib> #include <cstring> const int N = 105; using namespace std; vector<int>G[N]; int n,dfn[N],tim,low[N],stk[N],top,id[N],cnt,v[N],w[N],head[N],ecnt,eecnt,hd[N],m; bool vis[N]; struct Node { int w,v; } s[N]; struct Edge { int to,nxt; } e[N<<1]; void add(int bg,int ed) { e[++ecnt].nxt=head[bg]; e[ecnt].to=ed; head[bg]=ecnt; } void tarjan(int x) { low[x]=dfn[x]=++tim; stk[++top]=x; vis[x]=1; for(int i=head[x],u; i; i=e[i].nxt) { u=e[i].to; if(!dfn[u]) { tarjan(u); low[x]=std::min(low[x],low[u]); } else if(vis[u]) low[x]=std::min(low[x],dfn[u]); } if(dfn[x]==low[x]) { int k; ++cnt; do { k=stk[top--]; vis[k]=0; id[k]=cnt; s[cnt].v+=v[k],s[cnt].w+=w[k]; } while(k!=x); } } int f[N][N*5],ru[N]; void dp(int x){ if(s[x].w>m)return; memset(f[x],0xcf,sizeof f[x]); for(int i=s[x].w;i<=m;i++) f[x][i]=s[x].v; for(int i=0;i<G[x].size();i++) { dp(G[x][i]); for(int j=m;j>=s[x].w;j--) { for(int k=j;k>=0;k--) { f[x][j]=max(f[x][j-k]+f[G[x][i]][k],f[x][j]); } } } } int main() { scanf("%d%d",&n,&m); for(int i=1,x; i<=n; i++) scanf("%d",&w[i]); for(int i=1,x; i<=n; i++) scanf("%d",&v[i]); for(int i=1,x; i<=n; i++) { scanf("%d",&x);if(x)add(x,i);} for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) { for(int j=head[i];j;j=e[j].nxt) { int v=e[j].to; if(id[v]!=id[i]){ G[id[i]].push_back(id[v]); ru[id[v]]++; } } } for(int i=1;i<=cnt;i++) if(!ru[i]){ dp(i); for(int j=m;j>=0;j--){ for(int k=j;k>=0;k--){ f[0][j]=max(f[0][j],f[i][k]+f[0][j-k]); } } } printf("%d",f[0][m]); }
T3
一道線段樹的操作題。也可以分塊ryc分塊寫挫
線段樹維護最長連續上升子序列裸題,寫掛交暴力。
#include <cstdio> #include <cstdlib> #include <algorithm> using std::max; const int N=1e6; struct Seg{ int l,r,len;double mx; }t[N<<2]; void build(int l,int r,int cur){ t[cur].l=l;t[cur].r=r; if(l==r){return;} int mid=(l+r)>>1; build(l,mid,cur<<1); build(mid+1,r,cur<<1|1); } int query(int cur,double hig) { if(t[cur].l==t[cur].r)return t[cur].mx>hig; if(t[cur<<1].mx>=hig) return t[cur].len-t[cur<<1].len+query(cur<<1,hig); else return query(cur<<1|1,hig); } void update(int cur,double hig,int now){ if(t[cur].l==t[cur].r) {t[cur].mx=hig,t[cur].len=1;return;} int mid=(t[cur].l+t[cur].r)>>1; if(mid>=now) update(cur<<1,hig,now); else update(cur<<1|1,hig,now); t[cur].mx=max(t[cur<<1].mx,t[cur<<1|1].mx); t[cur].len=t[cur<<1].len+query(cur<<1|1,t[cur<<1].mx); } int main(){ int n,m,x,y; scanf("%d%d%",&n,&m); build(1,n,1); while(m--){ scanf("%d%d",&x,&y); update(1,(double)y/(double)x,x); printf("%d\n",t[1].len); } }
總結:我太菜了,GhostCai不可能把我按在鍵盤上 !a~ 阿QASA發揮得犯的話題
重來:我太菜了,平時寫題細節上掛了就看題解,導致代碼查錯很菜啊,還有樹上的東西好像一直掌握的不太紮實網絡流大法好!
2018.7.3模擬賽