[bzoj]2131: 免费的馅饼

原题链接:免费的馅饼

题意

接饼子游戏,饼子每秒下落一格,然后人每秒可以向左或者向右移动一格或者两格,当然也可以原地不动。

问最多接到的饼子价值。

分析

发现网上的做法都是dp+树状数组优化的。

这里提供一个另外的思路。

由于每秒向左向右移动的步数可以是$0,1,2$步,转化在坐标系中可以是一个夹角,右边界的斜率$k=\frac{\sqrt{5}}{5}$。

我们可以旋转坐标系,让$x$轴和右边界对齐,然后再旋转$y$轴,把原坐标系变为一个斜坐标系,这样子我们接完每个饼之后只能向$x,y$的正方向移动。

然后按照横坐标排序之后就变成一个求一个带权$LIS$的问题了。

怎么处理带权$LIS$呢,拆点,每个权值为$v_i$的点拆成$v_i$个点,这样就不带权了,然后求个$LIS$就行了。

但是这里的$n*v_i$是$10^8$还需要一步优化。

我们开一个$double->int$的$std::map$,按照$nlogn$的$LIS$算法,每次插入一个值就查找后继,删除掉跟插入一样多的后继,如果后继不够说明答案增加。

把全部点都插完之后直接遍历$std::map$然后把所有的权值累加就行了

代码

#include <bits/stdc++.h>
#define ll long long
#define Mid ((l+r)>>1)
#define ull unsigned long long
using namespace std;
const double Pi=acos(1.0);
int read(){
    char c;int num,f=1;
    while(c=getchar(),!isdigit(c))if(c==‘-‘)f=-1;num=c-‘0‘;
    while(c=getchar(), isdigit(c))num=num*10+c-‘0‘;
    return f*num;
}
const int N=1e5+1009;
struct node{double x,y;int w;}a[N];
map<double,int>g;
map<double,int>::iterator it,it2;
int n,w;
double Sin,Cos,Sin2,Cos2;
bool cmp(node a,node b){return a.x<b.x;}
int main()
{
    Sin=1.0/sqrt(5);
    Cos=2.0/sqrt(5);
    Sin2=2*Cos*Cos-1;
    Cos2=2*Sin*Cos;
    w=read();n=read();
    for(int i=1;i<=n;i++){
        double y=read(),x=read(),p;
        a[i].w=read();
        a[i].x=Cos*x+Sin*y;a[i].y=Cos*y-Sin*x;
        //先把坐标系旋转到x轴与k=1/sqrt(5)相同
        x=a[i].x;y=a[i].y;
        a[i].x=x+y*Sin2/Cos2;a[i].y=y/Cos2;
        //再把直角坐标系映射到斜坐标系
    }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++){
        int t=a[i].w;
        if(g.find(a[i].y)!=g.end())g[a[i].y]+=t;
        else g[a[i].y]=t;
        it=++g.find(a[i].y);
        while(t&&it!=g.end()){
            if((it->second)<=t){
                it2=it++;
                t-=(it2->second);
                g.erase(it2);
            }else{
                (it->second)-=t;
                t=0;
            }
        }

    }
    int ans=0;
    for(it=g.begin();it!=g.end();it++)
        ans+=(it->second);
    printf("%d\n",ans);
    return 0;
}
/*
建立坐标系,发现每次移动都是45度角
旋转坐标系变为45度角,求最长不下降子序列即可
虽然带权,但是点权很小,直接把一个点拆成点权个数个点 

*/ 

原文地址:https://www.cnblogs.com/onglublog/p/11325459.html

时间: 2024-10-11 11:13:11

[bzoj]2131: 免费的馅饼的相关文章

[bzoj2131]免费的馅饼_树状数组

免费的馅饼 bzoj-2131 题目大意: 注释:$1\le n \le 10^5$,$1\le w \le 10^8$. 想法:首先,想到dp 状态:dp[i][j]表示i分钟在位置j的最大收益 优化优化 状态:dp[i]表示最后收到i的最大收益. 转移:顺序枚举i:1->n即可. 然后,我们尝试优化 对于这个状态我们会发现转移的时候有一个绝对值的死东西,我们将它拆开就有: 2*t[j]+pos[j]<=2*t[i]+pos[i]且2*t[j]-pos[j]<=2*t[i]-pos[i

免费的馅饼 HYSBZ - 2131 (树状数组维护二维偏序)

题目链接:https://cn.vjudge.net/problem/HYSBZ-2131 题目大意:中文题目 具体思路:对于任意的两个位置,posA和posB,我们可以如下推导. |posA-posB|<=2*(tA-tB) 2*tB-2*tA<=posA-posB<=2*tB-2*tA. 2*tA+posA>=2*tB+posB  || 2*tA -pos A > = 2*tB-posB.(注意这个地方,只要有一个满足就可以了) 然后我们对2*tA+posA进行排序,每一

BZOJ 3624 免费道路

第一反应:这不先0后1做并查集就行了吗? 然后WA了... 哦....啊?哦...233 如果按顺序做并查集,有些0的边可能很重要(只能由它作为0连起两个联通块),但并没有被选. 于是先按1做并查集,选出这些边,再按0,1做并查集. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 20050 #define maxe 100500 u

【bzoj2131】免费的馅饼 dp+树状数组

题解: 昨天好像做了个几乎一模一样的题目 按照ti排序 |p[i]-p[j]|<=2*(t[i]-t[j]) 然后去绝对值变为三维偏序 发现后两个式子可以推出ti<tj 所以就变成二维偏序 按照一个排序套树状数组就可以了 原文地址:https://www.cnblogs.com/yinwuxiao/p/9665328.html

bzoj2131: 免费的馅饼

首先我们很容易看出是一个DP 然后容易看出是数据结构优化DP 但是这个限制条件有点鬼畜: abs(p[i]-p[j])/2<=(t[i]-t[j]) p[i]>p[j] -> t[i]*2-p[i]>=t[j]*2-p[j] p[i]<p[j] -> t[i]*2+p[i]>=t[j]*2+p[j] 这样的话我只会树套树(后来想想带修主席树应该也行?).....信仰不够去%题解 结果发现这两个东西是可以放在一起的,也就是说如果满足p[i]>p[j]和t[i]

hdu 1176 免费馅饼

免费馅饼 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 26519 Accepted Submission(s): 9032 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内.

Hdoj 1176 免费馅饼 【动态规划】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 26110    Accepted Submission(s): 8905 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

[2016-03-29][HDU][1176][免费馅饼]

时间:2016-03-29 09:46:34 星期二 题目编号:[2016-03-29][HDU][1176][免费馅饼] #include <algorithm> #include <cstring> #include <cstdio> using namespace std; const int maxt = 100000 + 10; int dp[maxt][11]; int a[maxt][11]; int main(){ int n,x,t,maxT; whi

hdoj 1176 免费馅饼

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 28601    Accepted Submission(s): 9760 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10