zoukankan      html  css  js  c++  java
  • 20180703 考试记录

    T1 [luogu2920 USACO08NOV]时间管理

    题解:

    直接贪心(排序递推),注意处理-1的情况
    code:

    //By Menteur_Hxy
    #include <map>
    #include <set>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define LL long long
    #define M(a,b) memset(a,(b),sizeof(a))
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    #define C(i,a,b) for(register int i=(b);i>=(a);i--)
    #define E(i,u) for(register int i=head[u];i;i=nex[i])
    using namespace std;
    
    inline LL rd() {
        LL x=0,fla=1; char c=' ';
        while(!isdigit(c)) {if(c=='-') fla=-fla; c=getchar();}
        while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
        return x*fla;
    }
    
    inline void out(LL x){
        int a[25],wei=0;
        if(x<0) putchar('-'),x=-x;
        for(;x;x/=10) a[++wei]=x%10;
        if(wei==0){ puts("0"); return;}
        for(int j=wei;j>=1;--j) putchar('0'+a[j]);
        putchar('
    ');
    }
    
    const int N=100010;
    int n,s;
    
    struct things{
        int t,s;
        bool operator < (const things x) {return s>x.s;}
    }th[N];
    
    int main() {
    //	freopen("manage.in","r",stdin);
    //	freopen("manage.out","w",stdout);
        n=rd();
        F(i,1,n) th[i].t=rd(),th[i].s=rd();
        sort(th+1,th+1+n);
        int ans=0x3f3f3f3f;
        F(i,1,n) {
            if(th[i].s>=ans) ans-=th[i].t;
            else if(th[i].s<ans) ans=th[i].s-th[i].t;
        }
        if(ans<0) return out(-1),0;
        return out(ans),0;
    }
    

    T2 [luogu2515 HAOI2010]软件安装

    题解:

    考虑给出图的性质,发现有三种图(可能同时出现):
    纯树,纯环,树的根是环
    所以我们可以缩点跑树形dp
    考试时dp写错40分(手写数据失败,居然还有分
    code:

    //By Menteur_Hxy
    #include <map>
    #include <set>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define LL long long
    #define M(a,b) memset(a,(b),sizeof(a))
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    #define C(i,a,b) for(register int i=(b);i>=(a);i--)
    #define E(i,u) for(register int i=head[u];i;i=nxt[i])
    using namespace std;
    
    inline LL rd() {
        LL x=0,fla=1; char c=' ';
        while(!isdigit(c)) {if(c=='-') fla=-fla; c=getchar();}
        while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
        return x*fla;
    }
    
    inline void out(LL x){
        int a[25],wei=0;
        if(x<0) putchar('-'),x=-x;
        for(;x;x/=10) a[++wei]=x%10;
        if(wei==0){ puts("0"); return;}
        for(int j=wei;j>=1;--j) putchar('0'+a[j]);
        putchar('
    ');
    }
    
    const int N=110,M=510;
    int n,m,ecnt;
    int vis[N<<2],we[N<<2],va[N<<2],dp[N<<2][M];
    int to[N<<2],nxt[N<<2],head[N<<2];
    
    void add(int a,int b) {
        nxt[++ecnt]=head[a]; to[ecnt]=b; head[a]=ecnt; 
    }
    
    int top,sta[N<<2],vist[N<<2],del[N<<2],flag;
    void dfs(int u) { //tarjan弱化版
        if(flag) return ;
        sta[++top]=u;vis[u]=vist[u]=1;
        E(i,u) { int v=to[i];
            if(vis[v]&&vist[v]==0) continue;
            else if(!vist[v]) dfs(v);
            else {
                n++;add(0,n);//新点连向虚根
                while(sta[top]!=v) {
                    del[sta[top]]=1;
                    we[n]+=we[sta[top]],va[n]+=va[sta[top]];
                    E(j,sta[top]) add(n,to[j]);
                    top--;
                }
                del[sta[top]]=1;
                we[n]+=we[sta[top]],va[n]+=va[sta[top]];
                E(j,sta[top]) add(n,to[j]);
                top--;
                flag=1;//一个部分只会有一个环
            }
        }
        vist[u]=0;top--;
    }
    
    void print(int x) {
        F(i,0,m) cout<<dp[x][i]<<" ";
        cout<<endl;
    }
    
    void dfs2(int u) {
        F(i,we[u],m) dp[u][i]=va[u];
        E(i,u) {
            int v=to[i]; if(del[v]) continue;
            dfs2(v);
            C(j,we[u],m) F(k,0,j-we[u]) 
            //考试时就这两行dp写错直接40分
            	dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
        }
    }
    
    int main() {
    //	freopen("software.in","r",stdin);
    //	freopen("software.out","w",stdout);
        n=rd(),m=rd();
        F(i,1,n) we[i]=rd();
        F(i,1,n) va[i]=rd();
        F(i,1,n) add(rd(),i);
        F(i,1,n) if(!vis[i]) flag=top=0,dfs(i);
        dfs2(0);
        int ans=0;
    //	cout<<endl;
    //	F(i,0,n) print(i);
        F(i,0,m) if(dp[0][ans]<dp[0][i]) ans=i;
        out(dp[0][ans]);
        return 0;
    }
    /* 假*手造数据
    11 12
    1 2 4 7 6 2 3 3 1 1 1
    2 4 6 8 10 7 4 1 2 4 5
    3 1 2 3 4 0 6 7 11 9 10
    */ 
    

    T3 [luogu4198] 楼房重建

    题解:

    分析题目发现是要求斜率严格上升的数据个数
    那么我们用线段树对斜率实现分治
    我们在线段树中记录两个值:最大值(ma[cur])和严格上升序列长度(sum[cur])
    由于一开始所有楼房为0所以只需update和pushup操作(答案为sum[1])
    update和pushup(ma[cur])好说,关键是对sum[cur]的pushup操作
    我们将x处的斜率值修改,那么显然x左边的sum值不变直接加上
    对于x右边的所有区间,我们判断其中的左区间ma值是否大于x
    若大于,那么去统计右区间的答案
    若小于,那么就用右区间的值+左区间统计出的答案
    Q:为什么直接加上右区间的值?
    A:根据性质我们知道右区间(cur<<1|1)统计在答案中的值(sum[cur]-sum[cur<<1])一定比左区间的大,所以直接加上
    Q:为什么右区间的值是(sum[cur]-sum[cur<<1])而不是(sum[cur<<1|1])
    A:因为sum[cur<<1|1]仅仅表示在右区间中的单调序列长度,其中统计到的斜率值不一定比左区间的大,所以统计到(sum[cur])中的右区间斜率值<=(sum[cur<<1|1])
    eg: (1,2,3)(2,3,4)->(1,2,3,4) 右区间贡献:1
    考试时n^2暴力QAQ
    code:

    //By Menteur_Hxy
    #include <map>
    #include <set>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define LL long long
    #define M(a,b) memset(a,(b),sizeof(a))
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    #define C(i,a,b) for(register int i=(b);i>=(a);i--)
    #define E(i,u) for(register int i=head[u];i;i=nex[i])
    using namespace std;
    
    inline LL rd() {
        LL x=0,fla=1; char c=' ';
        while(!isdigit(c)) {if(c=='-') fla=-fla; c=getchar();}
        while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
        return x*fla;
    }
    
    inline void out(LL x){
        int a[25],wei=0;
        if(x<0) putchar('-'),x=-x;
        for(;x;x/=10) a[++wei]=x%10;
        if(wei==0){ puts("0"); return;}
        for(int j=wei;j>=1;--j) putchar('0'+a[j]);
        putchar('
    ');
    }
    
    const int N=200010;
    int n,m;
    int sum[N<<1];
    double ma[N<<1];
    
    inline void pushup1(int cur) {
        ma[cur]=max(ma[cur<<1],ma[cur<<1|1]);
    }
    
    inline int pushup2(int cur,int l,int r,double x) {
        if(ma[cur]<=x) return 0;
        if(l==r) return ma[cur]>x;
        int mid=(l+r)>>1;
        if(ma[cur<<1]<=x) return pushup2(cur<<1|1,mid+1,r,x);
        else return pushup2(cur<<1,l,mid,x)+sum[cur]-sum[cur<<1];
    }
    
    inline void update(int cur,int l,int r,int id,double x) {
        if(l==r) {
            sum[cur]=1;
            ma[cur]=x;
            return ;
        }
        int mid=(l+r)>>1;
        if(id<=mid) update(cur<<1,l,mid,id,x);
        else update(cur<<1|1,mid+1,r,id,x);
        pushup1(cur);
        sum[cur]=sum[cur<<1]+pushup2(cur<<1|1,mid+1,r,ma[cur<<1]);
    }
    
    int main() {
        n=rd(),m=rd();
        F(i,1,m) {
            int x=rd(),y=rd();
            double k=(double)y/(double)x;
            update(1,1,n,x,k);
            printf("%d
    ",sum[1]);
        }
        return 0;
     }
    
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    Hdu5093 Battle ships 二分图
    Hdu 4081 最小生成树
    POJ1201 Intervals差分约束系统(最短路)
    poj1222 EXTENDED LIGHTS OUT 高斯消元||枚举
    Gym 100814C Connecting Graph 并查集+LCA
    Fzu2109 Mountain Number 数位dp
    poj 2774 Long Long Message 后缀数组基础题
    Uva12206 Stammering Aliens 后缀数组&&Hash
    hdu 3518 Boring counting 后缀数组基础题
    数据结构复习之开题篇(持续更新)
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9260264.html
Copyright © 2011-2022 走看看