Problem A: 传送带

Time Limit: 1000 ms Memory Limit: 256 MB

Description

在一个二维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。小y在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在,小y想从A点走到D点,请问他最少需要走多长时间。

Input

第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By。

第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy。

第三行是3个整数,分别是P,Q,R。

Output

输出一行一个数,表示小y从A点走到D点的最短时间,保留到小数点后2位。

Sample Input
0 0 0 100
100 0 100 100
2 2 1
Sample Output
136.60

HINT

对于30%的数据满足:

1<=Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=10

1<=P,Q,R<=5

对于100%的数据满足:

1<=Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000

1<=P,Q,R<=10

Solution

三分板子题?

首先三分起始点与A的距离,然后再套一个三分算出从起始点出发到达CD上某一点的最小距离即可。

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-4;
struct point{double x,y;point(){}point(double xx,double yy){x=xx,y=yy;}
}A,B,C,D;
double AB,CD;
double p,q,r;
point operator +(point a,point b){return point(a.x+b.x,a.y+b.y);
}
point operator -(point a,point b){return point(a.x-b.x,a.y-b.y);
}
point operator *(point a,double k){return point(a.x*k,a.y*k);
}
double dis(point a,point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double cal(point X,double x){point tmp=C;if(CD!=0.0){tmp=(C+(D-C)*(x/CD));}return dis(X,tmp)/r+(CD-x)/q;
}
double calc(double x){point tmp=A;if(AB!=0.0){tmp=(A+(B-A)*(x/AB));}double l=0,r=CD;while(r-l>eps){double mid=(l+r)/2.0;double m1=(mid-eps/2.0),m2=(mid+eps/2.0);if(cal(tmp,m1)<=cal(tmp,m2)){r=mid;}else l=mid;}return x/p+cal(tmp,(l+r)/2.0);
}
int main(){scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);scanf("%lf%lf%lf%lf",&C.x,&C.y,&D.x,&D.y);scanf("%lf%lf%lf",&p,&q,&r);AB=dis(A,B),CD=dis(C,D);double l=0,r=AB;while(r-l>eps){double mid=(l+r)/2.0;double m1=(mid-eps/2.0),m2=(mid+eps/2.0);//cout<<calc(m1)<<" "<<calc(m2)<<endl; if(calc(m1)<=calc(m2)){r=mid;}else l=mid;}//printf("%.2lf\n",(l+r)/2.0);printf("%.2lf\n",calc((l+r)/2.0));
}

Problem B: 疯狂的火神

Time Limit: 1000 ms Memory Limit: 256 MB

Description

火神为了检验zone的力量,他决定单挑n个人。

由于火神训练时间有限,最多只有t分钟,所以他可以选择一部分人来单挑,由于有小y的帮助,他得到了每个人特定的价值,每个人的价值由一个三元组(a,b,c)组成,表示如果火神在第x分钟单挑这个人,他就会得到a-b*x的经验值,并且他需要c分钟来打倒这个人。

现在火神想知道,他最多可以得到多少经验值,由于火神本来就很笨,进入zone的疯狂的火神就更笨了,所以他希望你来帮他计算出他最多可以得到多少经验值。

Input

第一行一个正整数T,表示数据组数。

对于每组数据,第一行为两个正整数n和t,表示跟火神单挑的人的个数和火神的训练时间。下面n行,每行三个正整数Ai,Bi,Ci,表示每个人的价值,含义见题目。

Output

对于每组数据输出一行一个整数,表示火神最多能得到多少经验值。

Sample Input
1
4 10
110 5 9
30 2 1
80 4 8
50 3 2
Sample Output
88

HINT

对于20%的数据满足:1≤n≤10

对于50%的数据满足:1≤n≤18

对于100%的数据满足:1≤n≤1000,1≤t≤3000,1≤Ci≤t,Ai≤10^6

保证n>200的数据组数不超过5组,其他的数据组数不超过10组

保证每个人贡献的经验值到训练结束都不会变成负数

Solution

恕我直言题目描述就是一坨shit!

他的经验值获取的计算是在击败后才算的。

考虑对于当前某一时间下怎样选才能最大化自己所获得的经验。

因为经验会随着时间流逝,所以对于任意一个选择的组合,一定是减的比较多的优先选择。

证明:设两个人他们的b值和c值分别为\(b1,c1,b2,c2\),且有\({b1 \over c1} > {b2 \over c2}\)

则如果让1在前面,所失去的经验是\(b1 \times c1+b2 \times (c1+c2)\),否则就是\(b2 \times c2+b1 \times (c1+c2)\)

两边都减去\(b1 \times c1+b2 \times c2\),留下来的就是\(b2 \times c1\)和$ b1 \times c2$

结合最上面的式子,可以得到\(b2 \times c1 < b1 \times c2\)

所以我们要让1排在前面。

于是我们按照c/b排序然后直接单次背包DP即可。

#include<bits/stdc++.h>
using namespace std;
struct sb{int a,b,c;
}a[200001];
bool operator <(sb x,sb y){return x.c*1ll*y.b<x.b*1ll*y.c;
}
int dp[200001];
int main(){int T;scanf("%d",&T);while(T--){memset(dp,0,sizeof(dp));int n,t;scanf("%d%d",&n,&t);for(int i=1;i<=n;++i){scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);}sort(a+1,a+1+n);//for(int i=1;i<=n;++i){//cout<<a[i].a<<" "<<a[i].b<<" "<<a[i].c<<endl;//}for(int i=1;i<=n;++i){for(int j=t-a[i].c;~j;--j){//cout<<j<<endl;dp[j+a[i].c]=max(dp[j+a[i].c],dp[j]+a[i].a-(a[i].b*(j+a[i].c)));}}int ans=0;for(int i=0;i<=t;++i)ans=max(ans,dp[i]);printf("%d\n",ans);}
}

Problem C: 火神的鱼

Time Limit: 5000 ms Memory Limit: 256 MB

Description

火神最爱的就是吃鱼了,所以某一天他来到了一个池塘边捕鱼。池塘可以看成一个二维的平面,而他的渔网可以看成一个与坐标轴平行的矩形。

池塘里的鱼不停地在水中游动,可以看成一些点。有的时候会有鱼游进渔网,有的时候也会有鱼游出渔网。所以火神不知道什么时候收网才可以抓住最多的鱼,现在他寻求你的帮助。

他对池塘里的每条鱼都给予了一个标号,分别从1到n标号,n表示池塘里鱼的总数。鱼的游动可以概括为两个动作:

1 l r d : 表示标号在[l,r]这个区间内的鱼向x轴正方向游动了d个单位长度。

2 l r d:表示标号在[l,r]这个区间内的鱼向y轴正方向游动了d个单位长度。

在某些时刻,火神会询问你现在有多少条鱼在渔网内(边界上的也算),请你来帮助他吧。

Input

第一行包含一个整数T,表示测试数据组数。对于每组测试数据:

第一行包含一个整数n,表示鱼的总数。

第二行包含四个整数x1,y1,x2,y2,表示渔网的左下角坐标和右上角坐标。

接下来n行,每行两个整数xi,yi,表示标号为i的鱼初始时刻的坐标。

再接下来一行包含一个整数m,表示后面的事件数目。

再接下来的m行,每行为以下三种类型的一种:

1 l r d : 表示标号在[l,r]这个区间内的鱼向x轴正方向游动了d个单位长度。

2 l r d:表示标号在[l,r]这个区间内的鱼向y轴正方向游动了d个单位长度。

3 l r : 表示询问现在标号在[l,r]这个区间内的鱼有多少在渔网内。

Output

对于每组数据的每个询问,输出一个整数表示对应的答案。

Sample Input
1
5
1 1 5 5
1 1
2 2
3 3
4 4
5 5
3
3 1 5
1 2 4 2
3 1 5
Sample Output
5
4

HINT

对于30%的数据满足:1≤n,m≤1000

对于100%的数据满足:1≤T≤10,1≤n,m≤30000,1≤l≤r≤n,1≤d≤10^9,x1≤x2,y1≤y2。保证任意时刻所有涉及的坐标值在[−10^9,10^9]范围内。

Solution

我们种两棵线段树,一棵维护每个点的x坐标,一棵维护y坐标。

令minx为矩阵左下角的x坐标,maxx为矩阵右上角的x坐标,miny、minx同理。

之后对每个坐标分三类:(这里只写了x坐标,y坐标以此类推)

1、x<minx 这种情况我们记录一下他到minx的距离,然后每次修改就把这个距离减掉相应的数,小于0时,我们把它归到第二类。

2、minx<=x<=maxx 这种情况记录他到maxx的距离,同上的修改,然后对于这部分的点检测:如果其y坐标也满足在矩阵内,我们的答案就+1。如果距离小于0,归到第三类。

3、maxx<x 我们直接把这个距离设为inf就好了,然后不管他。

对于每个区间的min值,只要修改后小于0,我们就重新统计这个区间的答案。

重新统计答案的时候用树状数组记录一下每个点是否在矩阵内就可以做到\(O(log n)\)的询问了。

由于每个点只要大于maxx我们就不管了,所以每个点实际上最多只会更新2次,总共修改的复杂度是\(O(n log n)\)的。

但是不知道是我写丑了还是怎么样,反正是擦着时限过的,荣获跑得最慢。

#include<bits/stdc++.h>
using namespace std;
inline int read(){int x=0;bool f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=0;for(;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)return x;return 0-x;
}
#define INF 2147483647
inline int lowbit(int x){return x&-x;}
int n;
int bit[200001];
inline void add(int x,int v){while(x<=n){bit[x]+=v;x+=lowbit(x);}
}
inline int query(int x){int res=0;while(x){res+=bit[x];x-=lowbit(x); }return res;
}
int op[2][2];
int pos[200001][2];
bool in[200001];
struct seg{int type;int minn[200001];int tag[200001];inline void change(int o,int l){add(l,-in[l]);in[l]=(pos[l][0]>=op[0][0]&&pos[l][0]<=op[0][1]&&pos[l][1]>=op[1][0]&&pos[l][1]<=op[1][1]);add(l,in[l]);if(pos[l][type]<op[type][0])minn[o]=op[type][0]-pos[l][type];else if(pos[l][type]<=op[type][1])minn[o]=op[type][1]-pos[l][type];else minn[o]=INF;}void build(int o,int l,int r){tag[o]=0;if(l==r){change(o,l);return;}int mid=(l+r)/2;build(o*2,l,mid);build(o*2+1,mid+1,r);minn[o]=min(minn[o*2],minn[o*2+1]);}void pushdown(int o){tag[o*2]+=tag[o],tag[o*2+1]+=tag[o];minn[o*2]-=tag[o],minn[o*2+1]-=tag[o];tag[o]=0; }void update(int o,int l,int r){if(l==r){pos[l][type]+=tag[o];tag[o]=0;change(o,l);return;}pushdown(o);int mid=(l+r)/2;update(o*2,l,mid);update(o*2+1,mid+1,r);minn[o]=min(minn[o*2],minn[o*2+1]);}void modify(int o,int l,int r,int L,int R,int val){if(L<=l&&r<=R){tag[o]+=val;minn[o]-=val;if(minn[o]<=0)update(o,l,r);return;}pushdown(o);int mid=(l+r)/2;if(L<=mid)modify(o*2,l,mid,L,R,val);if(mid<R)modify(o*2+1,mid+1,r,L,R,val);minn[o]=min(minn[o*2],minn[o*2+1]);}
}t[2];
int main(){int T;scanf("%d",&T);while(T--){memset(in,0,sizeof(in));memset(bit,0,sizeof(bit));n=read();op[0][0]=read(),op[1][0]=read(),op[0][1]=read(),op[1][1]=read();for(int i=1;i<=n;++i){pos[i][0]=read(),pos[i][1]=read();}t[0].type=0;t[1].type=1;t[0].build(1,1,n);t[1].build(1,1,n);int m;m=read();for(int i=1;i<=m;++i){int opt=read();if(opt==3){int l=read(),r=read();printf("%d\n",query(r)-query(l-1));}else {int l=read(),r=read(),val=read();t[opt-1].modify(1,1,n,l,r,val);}}}
} 

转载于:https://www.cnblogs.com/youddjxd/p/11423233.html

[补档]noip2019集训测试赛(十五)相关推荐

  1. [补档]noip2019集训测试赛(十)

    Problem A: fibonacci Time Limit: 2000 ms Memory Limit: 256 MB Description 小y最近迷上了fibonacci数列,他定义了一种数 ...

  2. [补档]noip2019集训测试赛(十二)

    Problem A: 记忆(memory) Time Limit: 1000 ms Memory Limit: 512 MB Description 你在跟朋友玩一个记忆游戏. 朋友首先给你看了n个长 ...

  3. [补档]noip2019集训测试赛(十四)

    Problem A: Fibonacci(fib.pas/cpp) Time Limit: 1000 ms Memory Limit: 128 MB Description 豆豆最近迷上了Fibona ...

  4. [补档]noip2019集训测试赛(九)

    因为这次考试我一道题都不会,所以先不写了 转载于:https://www.cnblogs.com/youddjxd/p/11442143.html

  5. [补档]noip2019集训测试赛(八)

    Problem B: 2048 Special Judge Time Limit: 1000 ms Memory Limit: 256 MB Description 2048曾经是一款风靡全球的小游戏 ...

  6. [补档]noip2019集训测试赛(十三)

    Problem A: Fairy Time Limit: 1000 ms Memory Limit: 256 MB Description 给定n个点,m条边的无向图(无自环),可以从图中删除一条边, ...

  7. noip2019集训测试赛(五)

    Problem A: lcm Time Limit: 1000 ms Memory Limit: 256 MB Sample Input 3 1 2 5 Sample Output 1 4 55 HI ...

  8. noip2019集训测试赛(七)

    Problem A: Maze Time Limit: 1000 ms Memory Limit: 256 MB Description 考虑一个N×M的网格,每个网格要么是空的,要么是障碍物.整个网 ...

  9. 2016集训测试赛(二十六)Problem A: bar

    Solution 首先审清题意, 这里要求的是子串而不是子序列... 我们考虑用1表示p, -1表示j. 用sum[i]表示字符串前\(i\)的前缀和. 则我们考虑一个字符串\([L, R]\)有什么 ...

最新文章

  1. c和python区别_C语言和python的区别
  2. python随机数程序源码_Python 实现随机数详解及实例代码
  3. WSL端口映射到win
  4. FFMPEG 视频图像解封装解码
  5. hive转16进制unhex_Java 进制的转换
  6. 减治求有重复元素的全排列
  7. 三季度OPPO 持续热销 R11s将成新爆款
  8. 开账户root远程桌面
  9. [转]如何写出让同事无法维护的代码?
  10. c# mysql存储过程 输出参数值_C#获取存储过程返回值和输出参数值的方法
  11. 树莓派学习(二):摄像头模块的安装和使用
  12. 【Axure报错】-Unable to connect to Axure Share. Please make sure you have an internet connection and try
  13. JS中的正则表达式(一)
  14. 【mmDetection框架解读】入门篇一、各组件解读,配置文件解读
  15. python3 parser
  16. 牛顿二项式定理(广义二项式定理)
  17. 如何获取微信公众平台图文消息的永久链接
  18. 阅读小结:MSR:From Captions to Visual Concepts and Back
  19. 微信小程序:电商发展蓝图解析
  20. 网络工具netstat与ss

热门文章

  1. ALEIS,啊,累死
  2. [HEOI2016/TJOI2016]求和(第二类斯特林数)
  3. sketch设置字体技巧(二)---通过组合法重新组建字体
  4. 基于c#的windows基础设计(学习日记1)【关于异或运算】
  5. maven local responsitory 手工新增jar
  6. 银联接口(注意项备忘)
  7. 修改lgoin,http://www.tuicool.com/articles/U3iyqq
  8. C++ 学习笔记----基础篇
  9. LeetCode(620)——有趣的电影(MySQL)
  10. malloc/free 与 new/delete的区别