POI2017

Flappy Bird:

水题,直接维护飞到每个柱子时的最高最低高度,然后用最低高度算答案。

代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=500010;
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n,X;
struct Node{int x,a,b;}A[Maxn];
int main()
{
    n=read(),X=read();
    int high=0,low=0;A[0].x=0;
    for(int i=1;i<=n;i++)
    {
        A[i].x=read(),A[i].a=read(),A[i].b=read();
        int t1=high+(A[i].x-A[i-1].x),t2=low-(A[i].x-A[i-1].x);
        if(A[i].a+1==A[i].b||t1<=A[i].a||t2>=A[i].b)return puts("NIE"),0;
        high=min(A[i].b-1,t1),low=max(A[i].a+1,t2);
        if(A[i].x&1)
        {
            if(!(high&1))high--;
            if(!(low&1))low++;
        }
        if(!(A[i].x&1))
        {
            if(high&1)high--;
            if(low&1)low++;
        }
        if(low>high)return puts("NIE"),0;
    }
    printf("%d",(low+A[n].x)/2);
}

Sabota?:

二分的话是非常水的题,不二分的话也不太难。注意到一定是某个子树的所有点一起叛变,所以直接树形DP, f [ x ] f[x] f[x]表示以 x x x为根子树全部叛变的最大比例即可。

代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=500010;
const int inf=2147483647;
const double eps=1e-7;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n,k,sz[Maxn];
vector<int>to[Maxn];
double f[Maxn];
void dfs(int x)
{
    sz[x]=0;
    if(!to[x].size()){sz[x]=f[x]=1;return;}
    f[x]=0;
    for(int i=0;i<to[x].size();i++)
    {
        int y=to[x][i];
        dfs(y);
        sz[x]+=sz[y];
    }
    for(int i=0;i<to[x].size();i++)
    {
        int y=to[x][i];
        f[x]=max(f[x],min((double)sz[y]/sz[x],f[y]));
    }
    sz[x]++;
}
int main()
{
    n=read();k=read();
    for(int i=2;i<=n;i++)to[read()].push_back(i);
    dfs(1);
    double ans=0;
    for(int i=1;i<=n;i++)
    if(sz[i]>k&&ans<f[i])ans=f[i];
    printf("%.10lf",ans);
}

Podzielno:

水题,显然的结论(由十进制联想一下就知道了嘛): B B B进制下的数,记 S ( x ) S(x) S(x) x x x的各位数字之和,则 x ≡ S ( x ) ( m o d &ThinSpace;&ThinSpace; ( B − 1 ) ) x\equiv S(x)(\mod(B-1)) xS(x)(mod(B1)),这个用归纳法证应该就好了吧,当位数为 1 1 1时,结论显然成立;当数位为 k k k时成立,数位为 k + 1 k+1 k+1也成立:设 x x x k k k位, y y y为一个 1 1 1位数, t = B x + y t=Bx+y t=Bx+y,则 t m o d &ThinSpace;&ThinSpace; ( B − 1 ) = S ( x ) × B m o d &ThinSpace;&ThinSpace; ( B − 1 ) + S ( y ) = S ( x ) + S ( y ) = S ( t ) t\mod(B-1)=S(x)\times B\mod (B-1)+S(y)=S(x)+S(y)=S(t) tmod(B1)=S(x)×Bmod(B1)+S(y)=S(x)+S(y)=S(t)。然后要尽量大,删一位就行了,询问二分一下。

代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=1000010;
const int inf=2147483647;
LL read()
{
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int B,q,a[Maxn],s=0;LL sum[Maxn],w=0;
int main()
{
    B=read(),q=read();
    for(int i=0;i<B;i++)a[i]=read(),s=(s+(LL)a[i]*i%(B-1))%(B-1),w+=a[i];
    if(s)a[s]--,w--;
    sum[B]=0;
    for(int i=B-1;i>=0;i--)sum[i]=sum[i+1]+a[i];
    while(q--)
    {
        LL x=w-read();
        if(x<=0)puts("-1");
        else
        {
            int l=0,r=B-1;
            while(l<=r)
            {
                int mid=l+r>>1;
                if(sum[mid]>=x)l=mid+1;
                else r=mid-1;
            }
            printf("%d\n",l-1);
        }
    }
}

Turysta:

点这里

Reprezentacje ró?nicowe:

这个题思考不够深入,没有做出来。只想到 l o g log log个数之后就会变得很大,做出贡献的一定是相邻的两个数,但是没有想到那些没有出现的差要怎么搞。其实数到了很大的时候,每次的 m e x mex mex也只会增加 1 1 1,用这个性质,二分一下还有几个数没有出现就可以了。

代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
map<int,bool>mp;
map<int,pair<int,int> >h;
int a[100],mex=1,n,b[2600],m=0;
int main()
{
    a[1]=1,a[2]=2;
    mp[1]=true;
    for(int i=3;;i++)
    {
        if(i&1)a[i]=(a[i-1]<<1);
        else
        {
            a[i]=a[i-1];
            for(int j=mex+1;;j++)
            if(!mp[j]){a[i]+=j;mex=j;break;}
        }
        for(int j=1;j<i;j++)mp[a[i]-a[j]]=true;
        if(a[i]>1000000000&&!(i&1)){n=i;break;}
    }
    for(int i=2;i<=n;i++)
    for(int j=1;j<i;j++)
    if(!h.count(a[i]-a[j]))b[++m]=a[i]-a[j],h[a[i]-a[j]]=make_pair(i,j);
    sort(b+1,b+1+m);
    int T=read();
    while(T--)
    {
        int x=read();
        if(h.count(x))printf("%d %d\n",h[x].first,h[x].second);
        else
        {
            int t=lower_bound(b+1,b+1+m,x)-b-1;
            printf("%d %d\n",(x-t)*2+n,(x-t)*2+n-1);
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值