2018.7.3模拟赛

我真的是菜的一笔

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发挥得犯的话题

重来:我太菜了,平时写题细节上挂了就看题解,导致代码查错很菜啊,还有树上的东西好像一直掌握的不太扎实网络流大法好!

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9259730.html