2016百度之星 补题记

2016"百度之星" - 复赛(Astar Round3)

1003 拍照

思路:先把所有的线段在x轴上可观察到的位置求出来,起点和终点对应数组a里的x,y,排序后从坐标最小开始枚举。如果遇到起点标志,就加一(说明从这个位置开始可以看见);结束点标志减一(说明从这个位置开始不可见)。还有一个值得注意的是:只有向左行驶的船只可见坐标大于向右行驶的船只,才可能在某个时刻同时出现在照片里

/**************************************************************
    Problem:hdu 5417
    User: youmi
    Language: C++
    Result: Accepted
    Time:1591MS
    Memory:1816K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d
",a)
#define ptlld(a) printf("%I64d
",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=4*atan(1.0);

using namespace std;
typedef long long ll;
inline 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*10+ch-'0'; ch=getchar();}
    return x*f;
}
const int maxn=20000+10;
int n,cnt,x,y,z,d,po,lmax,l,r,ans;
struct data
{
    int x,y,z;
}a[maxn];
bool cmp(data a,data b)
{
    if (a.x!=b.x) return a.x<b.x;
    else
    {
        if (a.y!=b.y) return a.y<b.y; else return a.z<b.z;
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    int T_T;
    scanf("%d",&T_T);
    for(int kase=1;kase<=T_T;kase++)
    {
        n=read(); cnt=0;
        for (int i=1;i<=n;i++)
        {
            x=read(),y=read(),z=read(),d=read();
            if (y-x<=2*z)
            {
                if (d==1) po=0; else po=1;
                a[++cnt].x=y-z; a[cnt].y=0; a[cnt].z=po;
                a[++cnt].x=x+z; a[cnt].y=1; a[cnt].z=po;
            }
        }
        sort(a+1,a+cnt+1,cmp);
        lmax=l=r=ans=0;
        for (int i=1;i<=cnt;i++)
        {
            if (a[i].z==0)
            {
                if (a[i].y==0) ++l; else --l;
            }
            else
            {
                if (a[i].y==0) ++r; else --r;
            }
            if (l>lmax) lmax=l;
            if (lmax+r>ans) ans=lmax+r;
        }
        printf("Case #%d:
%d
",kase,ans);
    }
    return 0;
}
View Code

2016"百度之星" - 初赛(Astar Round2B)

1001 区间的价值

思路:先选出[l,r]区间内的最小值,然后枚举[l,r]内的所以值,就可以算出以a[p]为最小值的所有区间的【区间的价值】了;不过有一点需要注意:在以a[p]为          最小值时,计算出的【区间大小大于等于3】(假设区间大小为k)的【区间的价值】,应该是区间大小为[2,k]内的最大值。

/**************************************************************
    Problem:hdu 5696
    User: youmi
    Language: C++
    Result: Accepted
    Time:1419MS
    Memory:4484K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d
",a)
#define ptlld(a) printf("%I64d
",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=4*atan(1.0);

using namespace std;
typedef long long ll;
template <class T> inline void read(T &n)
{
    char c; int flag = 1;
    for (c = getchar(); !(c >= '0' && c <= '9' || c == '-'); c = getchar()); if (c == '-') flag = -1, n = 0; else n = c - '0';
    for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) n = n * 10 + c - '0'; n *= flag;
}
int Pow(int base, ll n, int mo)
{
    if (n == 0) return 1;
    if (n == 1) return base % mo;
    int tmp = Pow(base, n >> 1, mo);
    tmp = (ll)tmp * tmp % mo;
    if (n & 1) tmp = (ll)tmp * base % mo;
    return tmp;
}
//***************************

int n;
const int maxn=200000+10;
int a[maxn];
ll ans[maxn];
ll temp[maxn];
void sovle(int l,int r)
{
    if(r<l)
        return ;
    int p=0;
    int len=(r-l+1);
    rep(i,0,len)
        temp[i]=0;
    rep(i,l,r)
    {
        if(a[i]<a[p])
            p=i;
    }
    rep(i,l,p)
        temp[p-l+1]=Max(temp[p-l+1],1ll*a[p]*a[i]);
    rep(i,p,r)
        temp[r-p+1]=Max(temp[r-p+1],1ll*a[p]*a[i]);
    rep(i,3,len)
        temp[i]=Max(temp[i],temp[i-1]);
    rep(i,1,len)
        ans[i]=Max(ans[i],temp[i]);
    sovle(l,p-1);
    sovle(p+1,r);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    while(~sc(n))
    {
        a[0]=oo;
        rep(i,1,n)
            sc(a[i]);
        zeros(ans);
        sovle(1,n);
        rep(i,1,n)
            ptlld(ans[i]);
    }
}
View Code

 1003 瞬间移动

思路:C(n-2,n+m-4);

1005 区间交

思路:对区间起末坐标存入数组排序,然后枚举,遇到起点存入队列,遇到末点更新答案。下面是具体做法:

用y数组记录下各个区间的id,l,r;并用x数组记录下区间的id,区间起(末)坐标并标记为起(末);对x数组进行排序,然后一一枚举x数组并将标记为起始点的坐标压入队列,这里的队列用数组实现。当然这个过程我们需要两个数组:index用来标记队列中点对应的区间id,pt用来标记区间id对应队列中的位置。如果为起始点,那么我们直接压入队列就好了。如果为末点,我们就得处理他。

处理操作:

  1. 首先,如果队列元素个数小于k,直接把队列中id对应的位置弹出去就好了,我们这里是标记为-1;
  2. 如果个数大于等于k,我们就更新答案。因为我们已经对x排序过,所以先进队列的起始坐标值肯定更小;而我们只需要k个区间交就可以了,所以我们取队列中的第k个值来计算。这里第k个值所对应队列中的位置我们用flag记录。
  3. 如果当前处理的id在队列中的位置在flag前面,那么flag指向的是k-1个区间交的位置,所以我们要不断向后寻找。因为被弹出队列的位置都被标记为-1,所以while循环到非-1就是当前的k个区间交对应的位置。
/**************************************************************
    Problem:hdu 5700
    User: youmi
    Language: C++
    Result: Accepted
    Time:1996MS
    Memory:7208K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d
",a)
#define ptlld(a) printf("%I64d
",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=4*atan(1.0);

using namespace std;
typedef long long ll;
template <class T> inline void read(T &n)
{
    char c; int flag = 1;
    for (c = getchar(); !(c >= '0' && c <= '9' || c == '-'); c = getchar()); if (c == '-') flag = -1, n = 0; else n = c - '0';
    for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) n = n * 10 + c - '0'; n *= flag;
}
int Pow(int base, ll n, int mo)
{
    if (n == 0) return 1;
    if (n == 1) return base % mo;
    int tmp = Pow(base, n >> 1, mo);
    tmp = (ll)tmp * tmp % mo;
    if (n & 1) tmp = (ll)tmp * base % mo;
    return tmp;
}
//***************************

int n,k,m;
const int maxn=100000+10;
int a[maxn];
ll sum[maxn];
struct T
{
    int id,l,r;
    void init(int _id,int _l,int _r)
    {
        id=_id,l=_l,r=_r;
    }
}y[maxn];
struct Y
{
    int id,p,dir;
    void init(int _id,int _p,int _dir)
    {
        id=_id,p=_p,dir=_dir;
    }
}x[maxn<<1];
bool cmp(struct Y b,struct Y c)
{
    if(b.p==c.p)
        return b.dir<c.dir;
    return b.p<c.p;
}

int index[maxn];
int pt[maxn];
void sovle()
{
    ll ans=0;
    zeros(pt);
    zeros(index);
    int head=1,sz=0,flag=-1;
    rep(i,1,2*m)
    {
        if(x[i].dir==0)
        {
            index[head]=x[i].id;
            pt[x[i].id]=head;
            head++,sz++;
            if(sz==k)
                flag=head-1;
        }
        else
        {
            if(sz>=k)
            {
                ans=Max(ans,sum[x[i].p]-sum[y[index[flag]].l-1]);
                if(pt[x[i].id]<=flag&&sz-1>=k)
                {
                    flag++;
                    while(index[flag]==-1&&flag<=head)
                    {
                        flag++;
                    }
                }
            }
            sz--;
            index[pt[x[i].id]]=-1;
        }
    }
    ptlld(ans);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    while(~sc3(n,k,m))
    {
        rep(i,1,n)
            sc(a[i]);
        sum[0]=0;
        sum[1]=a[1];
        rep(i,2,n)
            sum[i]=sum[i-1]+a[i];
        int l,r;
        rep(i,1,m)
        {
            sc2(l,r);
            x[i*2-1].init(i,l,0);
            x[i*2].init(i,r,1);
            y[i].init(i,l,r);
        }
        sort(x+1,x+1+2*m,cmp);
        sovle();
    }
}
View Code

1006 中位数计数

思路:这个题目可归类为01分数规划里总结果了,所以已经链接到那篇博文了

2016"百度之星" - 初赛(Astar Round2A)

1001 ALL X

思路:x*(10n-1)/9,之后的应该就简单了

1002  Sitting in Line

这个已经再博客里写过了,所以把标题已经连接到写的那个博客了

1003 snacks

思路:这个题要求一个子树里的最大值。先dfs一遍整棵树,并且记录一个点进入时候的id和出去的id,那么这两个id之间就是这个点的子树了。然后利用线段树处理一下,nlogn复杂度

/**************************************************************
    Problem:hdu 5692
    User: youmi
    Language: C++
    Result: Accepted
    Time:2355MS
    Memory:14932K
****************************************************************/
#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#include <ctime>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d
",a)
#define ptlld(a) printf("%I64d
",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=4*atan(1.0);
using namespace std;
typedef long long ll;
ll n,m;
ll z,x,y;
const int maxn=100000+10;
int in[maxn],out[maxn];
ll val[maxn];
ll dp[maxn];
int head[maxn];
int T=0,id;
struct side
{
    int v,next;
}e[maxn];
struct segment
{
    int l,r;
    ll mx,cg;
    void init(ll a,ll b,ll c,ll d)
    {
        l=a,r=b,mx=c,cg=d;
    }
}seg[maxn<<2];
inline 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*10+ch-'0'; ch=getchar();}
    return x*f;
}
void init()
{
    T=0;
    id=0;
    ones(head);
}
void build(int u,int v)
{
    e[T].v=v;
    e[T].next=head[u];
    head[u]=T++;
}
void dfs(int u,int f,ll c)
{
    in[u]=++id;
    if(u==0)
        dp[id]=c;
    else
        dp[id]=dp[in[f]]+c;
    for(int i=head[u];~i;i=e[i].next)
    {
        int v=e[i].v;
        if(v!=f)
            dfs(v,u,val[v]);
    }
    out[u]=id;
}
void pushup(int step)
{
    seg[step].mx=Max(seg[lson].mx,seg[rson].mx);
}
void pushdown(int step)
{
    seg[lson].mx+=seg[step].cg;
    seg[rson].mx+=seg[step].cg;
    seg[lson].cg+=seg[step].cg;
    seg[rson].cg+=seg[step].cg;
    seg[step].cg=0;
}
void build(int step,int l,int r)
{
    seg[step].init(l,r,0,0);
    if(l==r)
    {
        seg[step].init(l,r,dp[l],0);
        return;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(step);
}
void update(int step,int l,int r,ll c)
{
    if(seg[step].l==l&&seg[step].r==r)
    {
        seg[step].cg+=c;
        seg[step].mx+=c;
        return ;
    }
    pushdown(step);
    int mid=(seg[step].l+seg[step].r)>>1;
    if(l>mid)
        update(rson,l,r,c);
    else if(mid>=r)
        update(lson,l,r,c);
    else
    {
        update(lson,l,mid,c);
        update(rson,mid+1,r,c);
    }
    pushup(step);
}
ll query(int step,int l,int r)
{
    if(seg[step].l==l&&seg[step].r==r)
    {
        return seg[step].mx;
    }
    pushdown(step);
    int mid=(seg[step].l+seg[step].r)>>1;
    if(l>mid)
        return query(rson,l,r);
    else if(mid>=r)
        return query(lson,l,r);
    else
    {
        ll temp=query(lson,l,mid);
        temp=Max(temp,query(rson,mid+1,r));
        return temp;
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    int T_T;
    scanf("%d",&T_T);
    for(int kase=1;kase<=T_T;kase++)
    {
        printf("Case #%d:
",kase);
        n=read(),m=read();
        ll u,v;
        init();
        rep(i,1,n-1)
        {
            u=read(),v=read();
            build(u,v);
            build(v,u);
        }
        rep(i,0,n-1)
        {
            u=read();
            val[i]=u;
        }
        dfs(0,-1,val[0]);
        build(1,1,n);
        rep(i,1,m)
        {
            z=read(),x=read();
            if(z==1)
                ptlld(query(1,in[x],out[x]));
            else
            {
                y=read();
                ll temp=y-val[x];
                update(1,in[x],out[x],temp);
                val[x]+=temp;
            }
        }
    }
    return 0;
}
View Code

1005 BD String

思路:

1---B

2---BBD

3---BBD|B|BDD

4---BBD|B|BDD|B|BBD|D|BDD

5---BBD|B|BDD|B|BBD|D|BDD|B|BBD|B|BDD|D|BBD|D|BDD

从第五行可看出规律:每8个为一组,其中BBD,BDD连续重复;4的倍数上对应的字母,又是题给规律的出现,那么这部分进行dfs即可;然后对于小于等于8的部分,可以用一个数组预处理。

注意:(小于等于8的部分)与(4的倍数)在位置为4的地方重复计算了一次,所以要去掉这一部分

/**************************************************************
    Problem:hdu 5694
    User: youmi
    Language: C++
    Result: Accepted
    Time:0MS
    Memory:1572K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d
",a)
#define ptlld(a) printf("%I64d
",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=4*atan(1.0);

using namespace std;
typedef long long ll;
inline 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*10+ch-'0'; ch=getchar();}
    return x*f;
}
int b[]={0,1,2,2,0,3,3,3,0};
ll sovle(ll tt)
{
    if(tt==0)
        return 0;
    ll ans=0;
    ans+=sovle(tt/4);
    if(tt<4)
        return b[tt];
    else if(tt<8)
    {
        if(tt==4)
            return ans+b[3];
        else
            return ans+b[tt];
    }
    ans+=3*(tt/8);
    ans+=sovle(tt%8);
    if(tt%8>=4)
        ans-=1;
    return ans;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    int T_T;
    scanf("%d",&T_T);
    for(int kase=1;kase<=T_T;kase++)
    {
        ll l,r;
        l=read(),r=read();
        ll ans=sovle(r);
        ans-=sovle(l-1);
        ptlld(ans);
    }
}
View Code

 1006 Gym Class

这个贪心+拓扑就可以了,所以这里也直接把链接给到相应博客了

不为失败找借口,只为成功找方法
原文地址:https://www.cnblogs.com/youmi/p/5576111.html