[51Nod]NOIP2018提高组省一冲奖班模测训练(二)

http://www.51nod.com/contest/problemList.html#!contestId=73&randomCode=4408520896354389006

还是原题大赛

A.LXL的雕像

设有 \(t\) 行, \(s\) 列,那么有 \((t+1)\times x +t\times l=n,(s+1)\times x+s\times l=m\)

\(x\) 消掉,再整理一下得到 \((m+l)\times t-(n+l)\times s=n-m\)

到这里直接上exgcd,然后算就行了

复杂度 \(O(logn)\)

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

ll l,m,n,x,y;
ll gcd(ll a,ll b,ll&x,ll&y){
    if(!b){return x=1,y=0,a;}
    ll g=gcd(b,a%b,y,x);y-=a/b*x;
    return g;
}
int main(){
    cin>>l>>m>>n;
    if(l>m||l>n)return puts("-1"),0;
    ll g=gcd(m+l,-n-l,x,y);
    if((n-m)%g)return puts("-1"),0;
    ll s=n/l,p=abs((-n-l)/g);
    x=(x*(n-m)/g%p+p)%p;
    x+=(s-x)/p*p;
    if(n-x*l<0)puts("-1");else
    printf("%.6f",(double)(n-x*l)/(x+1));
    return 0;
}

B.ZYZ的游戏

先二分答案,问题转化为:把树分为几个联通块,使最长路不超过 \(m\) 最少需要切多少下

树形DP,设 \(f[x]\) 表示 \(x\) 所在联通块中以 \(x\) 为根的子树最大深度是多少

转移时,分两种情况

  1. \(f[y]>m/2\) 显然这样的 \(y\) 不能超过一个
  2. \(f[y]\le m/2\) 如果这里面最大的和第一种最小的加起来不超过 \(m\) 上面那一个就可以保留

复杂度 \(O(nlogn)\)

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int>pii;
inline int read(){char c,p=0;int w;
    while(isspace(c=getchar()));if(c=='-')p=1,c=getchar();
    for(w=c&15;isdigit(c=getchar());w=w*10+(c&15));return p?-w:w;
}
template<typename T,typename U>inline char smin(T&x,const U&y){return x>y?x=y,1:0;}
template<typename T,typename U>inline char smax(T&x,const U&y){return x<y?x=y,1:0;}
struct FastIO{
    static const int S=1310720;
    char buf[S],wbuf[S],*si=buf,*ti=buf,*so=wbuf,*to=wbuf+S;
    ~FastIO(){fwrite(wbuf,1,so-wbuf,stdout);}
    #define gc (si==ti&&(ti=buf+fread(si=buf,1,S,stdin),si==ti)?EOF:*si++)
    inline int read(){char c,p=0;int w;
        while(isspace(c=gc));if(c=='-')p=1,c=gc;
        for(w=c&15;isdigit(c=gc);w=w*10+(c&15));return p?-w:w;
    }
    #define pc(c) (so==to?fwrite(wbuf,1,S,stdout),so=wbuf,*so++=c:*so++=c)
    template<typename T>inline void print(T w,char c='\n'){
        static char s[25];int top=0;
        if(w<0)pc('-'),w=-w;if(w==0)pc('0');
        for(top=0;w;w/=10)s[++top]=w%10;
        while(top)pc(s[top--]|'0');pc(c);
    }
    #undef gc
}io;
#define read io.read
const int N=4e5+5;
int n,m,k,f[N],cnt;
vector<int>g[N];
void dfs(int x,int fa){
    f[x]=0;
    int m1=n+1,m2=0;
    for(int y:g[x])if(y!=fa){
        dfs(y,x);
        if(f[y]+1>(m>>1))++cnt,smin(m1,f[y]+1);
        else smax(m2,f[y]+1);
    }
    if(m1+m2<=m)--cnt,f[x]=m1;else f[x]=m2;
}
int main(){
    n=read(),k=read();
    REP(i,2,n){
        #define pb push_back
        int x=read(),y=read();g[x].pb(y),g[y].pb(x);
    }
    int l=0,r=n;
    while(l<r){
        m=l+r>>1;cnt=0;dfs(1,0);
        if(cnt<=k)r=m;else l=m+1;
    }
    cout<<l;
    return 0;
}

C.XYK的音游

\(j\) 能转移到 \(i\) 的条件是 \(abs(x[i]-x[j])\le p\times(t[i]-t[j])\)

去掉绝对值,移项, \(x[i]-p\times t[i]\le x[j]- p\times t[j],x[j]+p\times t[j]\le x[i]+p\times t[i]\)

左边的排序搞定,右边的树状数组搞定

排序的时候要注意!!,相等的时候再加 \(j<i\) 这个条件

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int>pii;
inline int read(){char c,p=0;int w;
    while(isspace(c=getchar()));if(c=='-')p=1,c=getchar();
    for(w=c&15;isdigit(c=getchar());w=w*10+(c&15));return p?-w:w;
}
template<typename T,typename U>inline char smin(T&x,const U&y){return x>y?x=y,1:0;}
template<typename T,typename U>inline char smax(T&x,const U&y){return x<y?x=y,1:0;}
struct FastIO{
    static const int S=1310720;
    char buf[S],wbuf[S],*si=buf,*ti=buf,*so=wbuf,*to=wbuf+S;
    ~FastIO(){fwrite(wbuf,1,so-wbuf,stdout);}
    #define gc (si==ti&&(ti=buf+fread(si=buf,1,S,stdin),si==ti)?EOF:*si++)
    template<typename T>inline void read(T&w){register char c,p=0;
        while(isspace(c=gc));if(c=='-')p=1,c=gc;
        for(w=c&15;isdigit(c=gc);w=w*10+(c&15));if(p)w=-w;
    }
    inline int read(){register int x;return read(x),x;}
    #define pc(c) (so==to?fwrite(wbuf,1,S,stdout),so=wbuf,*so++=c:*so++=c)
    template<typename T>inline void print(T w,char c='\n'){
        static char s[25];int top=0;
        if(w<0)pc('-'),w=-w;if(w==0)pc('0');
        for(top=0;w;w/=10)s[++top]=w%10;
        while(top)pc(s[top--]|'0');pc(c);
    }
    #undef gc
}io;
#define read io.read
const int N=1e5+5;
struct data{int t,w,p;}a[N];
int n,m,d,f[N],c[5100005];
inline bool cmp(data x,data y){return x.p-d*x.t>y.p-d*y.t||x.p-d*x.t==y.p-d*y.t&&x.p<y.p;}
const int R=5e6;
inline void add(int p,int x){for(;p<=R+n;p+=p&-p)smax(c[p],x);}
inline int ask(int p){int r=0;for(;p;p-=p&-p)smax(r,c[p]);return r;}
int main(){
    n=read();m=read(),d=read();
    REP(i,1,m)a[i]=(data){read(),read(),read()};
    sort(a+1,a+1+m,cmp);
    int r=0;
    REP(i,1,m){
        f[i]=ask(a[i].p+d*a[i].t)+a[i].w;
        add(a[i].p+d*a[i].t,f[i]);
        smax(r,f[i]);
    }
    cout<<r;
    return 0;
}

转载于:https://www.cnblogs.com/HolyK/p/9830419.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值