百度之星 初赛 BC

HDU  5691

这B题目 一看就知道不会

看题解  听说是状态 压缩  立刻就不想写了  今天状态好点 写一下

dp[i][j]   代表 i 这个状态  第j个当做结尾插入的  最大的加起来的和

初始化也很神奇

先初始化没每个状态的1的个数 然后转移  列举前一个 这个

#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
using namespace std;

#define LL   __int64
#define MAXN 10010
#define inf  1000000000

int cnt[(1<<16)+10];
int dp[(1<<16)+10][17];
int z[20],p[20];

int main()
{
    int t,ca;
    scanf("%d",&t);
    for(int i=1;i<=(1<<16);i++)
    {
        int a=i;
        while(a>0)
        {
            if(a%2==1)
                cnt[i]++;
            a=a/2;
        }
    }
    ca=1;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d %d",&z[i],&p[i]);
        for(int i=0;i<(1<<n);i++)
            for(int j=0;j<=n;j++)
                dp[i][j]=-inf;
        z[n]=0;
        dp[0][n]=0;

        for(int i=0;i<(1<<n);i++)
        {
            for(int j=0;j<=n;j++)
                if(dp[i][j]!=-inf)
                    for(int k=0;k<n;k++)
                    {
                        if(((1<<k)&i)==0&&(p[k]==-1||p[k]==cnt[i]))
                            dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+z[j]*z[k]);
                    }
        }
        int ans=-inf;
        for(int i=0;i<n;i++)
            ans = max(ans,dp[(1<<n)-1][i]);
        printf("Case #%d:\n%d\n",ca++,ans);
    }
    return 0;
}

HDU 5692

唯一的缺点就是没看到这是一棵树  0 开始到某个要去的点 显然不可能回来   哈哈哈  最多就只能走下去

感觉做过类似的  dfs 把每个点走一下标上号  然后 算出每个点到 父亲的距离  然后 转化到线段树上

怎么建树呢  1-n  带表 dfs序列  查询这个点就是 查询这个点 包括的子树的 l r    然后这个在dfs的时候就 处理出来了

然后 更新呢  就是 lazy   子树都要更新

更新的权值呢    y-w[b]   w[b]=y  真厉害    long long   哈哈哈

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
using namespace std;

#define ll  __int64
#define MAXN 100010
#define inf  1000000000000

int head[MAXN];
struct  edg
{
    int to,next;
}edge[MAXN*2];
int cnt,num;
ll w[MAXN],dis[MAXN],ls[MAXN],rs[MAXN],ind[MAXN];
void add(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
struct node
{
    int l,r;
    ll w,lz;
}tree[MAXN<<2];

void dfs(int u,int fa)
{
    num++;
    ls[u]=num;
    ind[num]=u;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa)
            continue;
        dis[v]=dis[u]+w[v];
        dfs(v,u);
    }
    rs[u]=num;
}
void Push_down(int a)
{
    tree[a<<1].lz+=tree[a].lz;
    tree[a<<1].w+=tree[a].lz;
    tree[a<<1|1].lz+=tree[a].lz;
    tree[a<<1|1].w+=tree[a].lz;
    tree[a].lz=0;
}
void Push_up(int a)
{
    tree[a].w=max(tree[a<<1].w,tree[a<<1|1].w);
}
void Build(int l,int r,int a)
{
    tree[a].l=l;
    tree[a].r=r;
    tree[a].lz=0;
    if(l==r)
    {
        tree[a].w=dis[ind[l]];
        return ;
    }
    int mid=(l+r)>>1;
    Build(l,mid,a<<1);
    Build(mid+1,r,a<<1|1);
    Push_up(a);
}
void Update(int l,int r,int l1,int r1,ll w1,int a)
{
    if(l1<=l&&r<=r1)
    {
        tree[a].w+=w1;
        tree[a].lz+=w1;
        return ;
    }
    int mid=(l+r)>>1;
    if(tree[a].lz)
        Push_down(a);
    if(l1<=mid)
        Update(l,mid,l1,r1,w1,a<<1);
    if(r1>mid)
        Update(mid+1,r,l1,r1,w1,a<<1|1);
    Push_up(a);
}
ll Ques(int l,int r,int l1,int r1,int a)
{
    ll mx=-inf;
    if(l1<=l&&r<=r1)
    {
        return tree[a].w;
    }
    int mid=(l+r)>>1;
    if(tree[a].lz)
        Push_down(a);
    if(l1<=mid)
        mx=max(mx,Ques(l,mid,l1,r1,a<<1));
    if(r1>mid)
        mx=max(mx,Ques(mid+1,r,l1,r1,a<<1|1));
    return mx;
}
int main()
{
    int t,ca;
    ca=1;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));
        cnt=0;
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        for(int i=0;i<n;i++)
            scanf("%I64d",&w[i]);
        num=0;
        dis[0]=w[0];
        dfs(0,-1);
        Build(1,num,1);
        printf("Case #%d:\n",ca++);
        while(m--)
        {
            int way;
            scanf("%d",&way);
            if(way==1)
            {
                int a;
                scanf("%I64d",&a);
                printf("%I64d\n",Ques(1,n,ls[a],rs[a],1));
            }
            else
            {
                int a;
                ll b;
                scanf("%d%I64d",&a,&b);
                Update(1,n,ls[a],rs[a],b-w[a],1);
                w[a]=b;
            }
        }
    }
    return 0;
}

时间: 2024-10-25 09:48:51

百度之星 初赛 BC的相关文章

数学 2015百度之星初赛2 HDOJ 5255 魔法因子

题目传送门 1 /* 2 数学:不会写,学习一下这种解题方式:) 3 思路:设符合条件的数的最高位是h,最低位是l,中间不变的部分为mid,由题意可得到下面的公式(这里对X乘上1e6用a表示,b表示1e6) 4 (h*power+l+mid)*a = (l*power+h+mid)*b 5 可推得:mid = ((h*power+l) * a - (l*power+h) * b) / (a - b); 6 所以可以枚举h,l然后求mid,注意mid的最低位一定是0,因为留出最低位加l或者h 7

2014百度之星初赛(第二场)——Best Financing

2014百度之星初赛(第二场)--Best Financing Problem Description 小A想通过合理投资银行理财产品达到收益最大化.已知小A在未来一段时间中的收入情况,描述为两个长度为n的整数数组dates和earnings,表示在第dates[i]天小A收入earnings[i]元(0<=i<n).银行推出的理财产品均为周期和收益确定的,可描述为长度为m的三个整数数组start.finish和interest_rates, 若购买理财产品i(0<=i<m),需要

HDU4828 Grids 2014百度之星初赛题解

看看Catalan数的公式:为 Catalan(n) = C(2n, n) / n+1 = C(2n, n) - C(2n, n-1); (公式0) 然后利用全排序表达:Catalan(n) = (2n)! / (n+1) * (n)!*n!; 那么Catalan(n-1) = (2(n-1))! / n * (n-1)!(n-1)!; 然后两者相除就得到:Catalan(n) = (4*n-2) / (n+1) (公式1)//这个就是递归的终极公式了. 一般使用动态规划的递推公式是:Catal

hdu 4832 百度之星初赛二B

把横的和竖的分开考虑 //#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<vector> #include<algorithm> #include<cstdio> #include<queue> #include<stack> #include<string> #include<ma

2014 百度之星初赛题解1001 - Energy Conversion

Problem Description 魔法师百小度也有遇到难题的时候-- 现在,百小度正在一个古老的石门面前,石门上有一段古老的魔法文字,读懂这种魔法文字需要耗费大量的能量和大量的脑力. 过了许久,百小度终于读懂魔法文字的含义:石门里面有一个石盘,魔法师需要通过魔法将这个石盘旋转X度,以使上面的刻纹与天相对应,才能打开石门. 但是,旋转石盘需要N点能量值,而为了解读密文,百小度的能量值只剩M点了!破坏石门是不可能的,因为那将需要更多的能量.不过,幸运的是,作为魔法师的百小度可以耗费V点能量,使

2014百度之星初赛(第二场)——JZP Set

2014百度之星初赛(第二场)--JZP Set Problem Description 一个{1, ..., n}的子集S被称为JZP集,当且仅当对于任意S中的两个数x,y,若(x+y)/2为整数,那么(x+y)/2也属于S. 例如,n=3,S={1,3}不是JZP集,因为(1+3)/2=2不属于S.但是{1,2,3}的其他子集都属于S,所以n=3时有7个JZP集 给定n,求JZP集的个数. Input 第一行为T,表示输入数据组数. 每组数据包含一行整数n. 限制条件 1<=T<=10^5

LIS 2015百度之星初赛2 HDOJ 5256 序列变换

题目传送门 1 /* 2 LIS(非严格):首先我想到了LIS,然而总觉得有点不对:每个数先减去它的下标,防止下面的情况发生:(转载) 3 加入序列是1,2,2,2,3,这样求上升子序列是3,也就是要修改2个,但是中间的两个2,变化范围又不能超过(1,3) 4 那么这样求的也就不对,但是减掉之后,相当于给中间重复的数留下了修改的空间 5 解释下为什么可以减而保持正确性:因为题目所求时严格递增,假设是2,3, 4,那么变成1, 1, 1,所以在LIS里非严格递增就可以了 6 这也是为什么要在upp

二分搜索 2015百度之星初赛1 1003 序列变换

题目传送门 1 /* 2 二分搜索:在0-1e6的范围找到最小的max (ai - bi),也就是使得p + 1 <= a[i] + c or a[i] - c 3 比赛时以为是贪心,榨干智商也想不出来:( 4 */ 5 #include <cstdio> 6 #include <algorithm> 7 #include <cstring> 8 #include <cmath> 9 #include <iostream> 10 using

二分查找 2015百度之星初赛1 1001 超级赛亚ACMer

题目传送门 1 /* 2 二分找到不大于m的最大的数,记做p,只要a[p] + k <= a[p+1]就继续 3 注意:特判一下当没有比m小的数的情况:) 4 */ 5 #include <cstdio> 6 #include <cstring> 7 #include <cmath> 8 #include <algorithm> 9 using namespace std; 10 11 typedef long long ll; 12 13 const