A组T1 bzoj 2674 Attack

Description

chnlich 非常喜欢玩三国志这款游戏,并喜欢用一些策略出奇制胜。现在,他要开始征服世界的旅途了。他的敌人有N 座城市和N 个太守, N个城市可以看作在二维平面上的N 个点。N 座城市的标号为0,1,2,......,N-1。第i 座城市的坐标为(Xi,Yi),镇守这座城市的太守的能力值为Zi。

chnlich 每次会选择一个边平行于坐标轴的矩形区域,并奇袭其中太守能力值第K小的城市(奇袭结束之后城市与太守依然存在)。

不过,他的敌人经常会偷偷交换两座城市的太守,防止弱点被chnlich 发现。

现在,chnlich 想要知道,每次奇袭时他的敌人的能力值。

Input

输入的第一行包含两个整数 N,M,N 表示城市与太守的个数,M 表示接下来发生了 M 个事件。

输入的第二行到第 N+1行,每行包含三个整数,第 i+2行的三个整数依次表示编号为 i 的城市的 Xi,Yi,Zi,含义如题所述。

输入的第 N+2行到第 N+M+1行,每行有两种可能形式:

第一种

QUERY x0 y0 x1 y1 k

表示 chnlich 询问一个相对顶点为(x0,y0),(x1,y1)的矩形中,第 k 小能力值太

守的能力值。

第二种

SWAP x y

表示 chnlich 的敌人交换了编号为 x 和 y 两座城市的太守。

Output

对于每一个 QUERY,输出一行。

若不存在第 k 小能力值的太守,输出"It doesn't exist."(不包含引号)。

否则输出一个整数,表示矩形内能力值第 k 小太守的能力值。

Sample Input

3 5
1 1 1
2 2 2
3 3 3
QUERY 1 1 3 3 3
SWAP 0 1
QUERY 2 2 4 4 1
SWAP 2 2
QUERY 2 2 3 3 3

Sample Output

3
1
It doesn't exist.

Data Constraint

Hint
对于100%的数据,N<=60000,M<=10000,0<=Xi,Yi,Zi<=10^9,k<=10^9,保证所有操作均合法。

分析

讲道理,这个题的正解十分毒瘤。BUT,OJ上有人手贱,于是1s时限变成了10s!!!!!!!!

对的,是10秒

直接给每个点按权值排序,询问时O(n)扫一遍就行了,遇到在矩形内的就记录个数直到遇到第k个就好了,交换时就直接交换。

复杂度为O(nm)

注意,矩形可能给出左上和右下两个端点,也可能给出左下和右上的两个端点。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,q[],ma[];char ch[];
struct node{int x,y,z;}p[];
bool cmp(int a,int b){return p[a].z<p[b].z;}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z),q[i]=i;
sort(q+,q++n,cmp);
for(int i=;i<=n;i++)ma[q[i]]=i;
for(int i=;i<=m;i++)
{
scanf("%s",ch+);
if(ch[]=='S')
{
int a,b;
scanf("%d%d",&a,&b);a++;b++;
swap(q[ma[a]],q[ma[b]]);swap(p[a].z,p[b].z);
swap(ma[a],ma[b]);
}
if(ch[]=='Q')
{
int x1,y1,x2,y2,k,cnt=,ans;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);
if(x1>x2)swap(x1,x2);
if(y1>y2)swap(y1,y2);
for(int i=;i<=n&&cnt<k;i++)
if(x1<=p[q[i]].x&&p[q[i]].x<=x2&&y1<=p[q[i]].y&&p[q[i]].y<=y2)
{cnt++;if(cnt==k){ans=q[i];break;}}
if(cnt<k)printf("It doesn't exist.\n");
else printf("%d\n",p[ans].z);
}
}
}

A组T2 bzoj 2676 Contra

Description

偶然间,chnlich 发现了他小时候玩过的一个游戏“魂斗罗”,于是决定怀旧。但是这是一个奇怪的魂斗罗 MOD。

有 N 个关卡,初始有 Q 条命。

每通过一个关卡,会得到 u 分和1条命,生命上限为 Q。其中 u=min(最近一次连续通过的关数,R)。

若没有通过这个关卡,将会失去1条命,并进入下一个关卡。

当没有生命或没有未挑战过的关卡时,游戏结束,得到的分数为每关得到的分数的总和。

由于 chnlich 好久不玩这个游戏了,每条命通过每个关卡的概率均为p(0<=p<=1),原先 chnlich 的最高分纪录是 S。

现在 chnlich 想要知道,当 p 至少为多少时,chnlich 期望获得的总分数能够超过原先的最高分。

Input

输入共一行,分别表示整数 N,整数 R,整数 Q,原先的最高分整数 S。

Output

输出共一行,若不存在这样的 p,输出"Impossible."(不包含引号),否则输出 p(保留6位小数)。

Sample Input

【样例输入一】
4 2 1 5

【样例输入二】
12 3 2 12

Sample Output

【样例输出一】
0.880606

【样例输出二】
0.687201

Data Constraint

Hint【数据说明】

对于20%的数据,N<=15

对于50%的数据,N<=10000

对于100%的数据,N<=10^8,1<=R<=20,1<=Q<=5,保证 S 是一个可能出现的分数。

【补充说明】

补充说明】

例如,当 N=12,R=3,Q=2时

第一关:未通过 u=0 获得分数0 总分为0 剩余生命1

第二关:通过 获得分数1 总分为1 剩余生命2

第三关:通过 获得分数2 总分为3 剩余生命2

第四关:通过 获得分数3 总分为6 剩余生命2

第五关:通过 获得分数3 总分为9 剩余生命2

第六关:未通过 获得分数0 总分为9 剩余生命1

第七关:通过 获得分数1 总分为10 剩余生命2

第八关:未通过 获得分数0 总分为10 剩余生命1

第九关:未通过 获得分数0 总分为10 剩余生命0

游戏结束 总分为10

这是 chnlich 游戏的一种可能性

假装分析

显然这是一道期望题(废话)。二分一下概率p,然后看dp出来的期望值是否比s大。

设dp[i][j][k]表示已经过了i关,连胜了j次,还剩下k条命的概率。

那么dp[i][j][k]就可以转移到dp[i+1][0][k-1](失败)和dp[i+1][min(j+1,r)][min(k+1,q)](成功)。(取min是因为超过了限制的状态贡献相同,可以合在一起)

则dp[i+1][0][k-1]+=dp[i][j][k]*(1-p),dp[i+1][min(j+1,r)][min(k+1,q)]+=dp[i][j][k]*p。

如何求期望值呢?

因为期望是可以分开求的,所以,每个状态dp[i][j][k]的贡献就是dp[i][j][k]*j,加起来就好啦。

不过这样是会TLE的,要用矩阵加速。

如果就直接拿来加速不好写,所以将j与k拿过来压成一个状态就行了,给每种(j,k)编个号。

另外还要一边乘一边计算答案,只需要修改一下矩阵,拿一个没用的编号来存答案即可。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define id(a,b) (min(a,r)*q+min(b,q))
using namespace std;
int n,m,q,r,s;
struct mar
{
double a[][];mar(){memset(a,,sizeof a);}
inline mar operator *(const mar &b)const
{
mar c;
for(int i=;i<=m;i++)for(int k=;k<=m;k++)for(int j=;a[i][k]>=1e-&&j<=m;j++)
c.a[i][j]+=a[i][k]*b.a[k][j];
return c;
}
};
inline bool pan(double p)
{
mar A,B,C;B.a[m][m]=1.0;//将之前的答案传递下来
for(int i=;i<=r;i++)for(int j=;j<=q;j++)
{
B.a[id(i,j)][id(i+,j+)]=p;
B.a[id(i,j)][m]=i;//计算每个状态对答案的贡献
if(j>)B.a[id(i,j)][id(,j-)]=1.0-p;
}
int k1=n+;for(int i=;i<=m;i++)C.a[i][i]=1.0;//n+1是因为dp[n][j][k]的答案之前没统计到,要多乘一次来统计。
while(k1){if(k1&)C=B*C;B=B*B;k1/=;}
A.a[][id(,q)]=1.0;A=A*C; return A.a[][m]>double(s);
}
int main()
{
scanf("%d%d%d%d",&n,&r,&q,&s);
double l1=,r1=,ans=;m=(r+)*q+;//m就是那个来存答案的编号
if(pan(r1)<1e-){printf("Impossible.");return ;}
while(r1-l1>*1e-)
{
double mid=(l1+r1)*0.5;
if(pan(mid))ans=mid,r1=mid;
else l1=mid;
}
printf("%.6lf",l1);
}

A组T3 bzoj 2675 Bomb

Description

A 国和 B 国是两个超级大国,长期处于冷战状态;

A 国在 B 国中设有 N 个情报站,编号为 1,2,3, …… ,N ,每个情报站有一个坐标 (Xi,Yi) 。但是, A 国的工作人员发现,每个情报站里都被埋上了炸弹!

这些炸弹非常特殊 , 只要同时拆除其中的三个炸弹 , 所有炸弹就都不会爆炸了。

由于各个情报站联络需要代价 , 拆除炸弹需要花费的总代价为这些炸弹两两之间的曼哈顿距离和。

现在 A 国的指挥部门找到了你 , 希望知道可能需要的最大代价和最小代价 。

Input

输入的第一行包含一个整数 N 。接下来 N 行,第 i+1 行两个整数 Xi,Yi ,表示第 i 个情报站的坐标。

Output

输出两行 , 每行包含一个整数 , 第一行表示可能的最大代价 , 第二行表示可能的最小代价。

Sample Input

4

1 1
1 2
2 1
2 3

Sample Output

6
4

Data Constraint

Hint
对于 30% 的数据, N<=500

对于另外 10% 的数据,每个点出现至少两遍

对于 50% 的数据, N<=1000

对于 60% 的数据, N<=8000

对于 70% 的数据, N<=15000

对于 80% 的数据, N<=50000

对于 100% 的数据, N<=100000 , 0<=Xi,Yi<=10^8

【 注释 】

对于两个点 (X0,Y0),(X1,Y1) ,

它们之间的曼哈顿距离为 abs(X0-X1)+abs(Y0-Y1) 。

抄题解的分析

先来看最大值(接下来是题解):

我们考虑三个点两两之间的曼哈顿距离和的实质。通过画图, 我们容易发现,问题的实质是求能包含这三个点的最小矩形的周长,即 2*(Xmax-Xmin+Ymax-Ymin),因此我们只要最大化和最小化 Xmax-Xmin+Ymax-Ymin 即可。 考虑这四个未知量,显然,一个点最多确定一个 X 未知量和一个 Y 未知量,答案的组成可 能有两种情况:

①一个点确定了一个 X 和一个 Y,另外两个点分别确定了一个 X 和一个 Y。

②一个点确定了一个 X 和一个 Y,另一个点同样确定了一个 X 和一个 Y,还有一个点 什么都没有确定(但必须存在这个点)。

我们分别考虑这两种情况。先考虑最大值。显然,确定最大值的点一定在 Xmax+Ymax,-Xmin+Ymax,-Xmin-Ymin,Xmax-Ymin,Xmin,Xmax,Ymin,Ymax 最大的至多 8个 点中选择三个,因此只需选出能使这些值变得最大的点暴力即可。

个人理解就是把曼哈顿距离的绝对值展开来进行维护,以X+Y的最大值为例,它能保证我们在这里取了一个点。用它减去X与Y的最小值。若X与Y的最小值属于同一个点,那么就是情况②,若不属于同一个点就是情况①。

再来看看最小值

本来最小值我打算想写线段树的,但网上一两百行的代码直接把我劝退了。于是又去找了一种分治的做法。可为什么我怎么看都像暴力加剪枝?

按照x排序后就直接分治,若点数小于15就直接暴力。合并的时候将两边距离中点距离小于当前最小答案的点拿出来,再按y值排序,再次暴力即可,如果一个点与另一个点的y值之差大于等于当前最小答案那么也要舍去。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int addmax,addmin,submax,submin,xmax,xmin,ymax,ymin,ansmax,ansmin;
struct node{int x,y;}p[],q[];
bool cmp1(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;}
bool cmp2(node a,node b){return a.y==b.y?a.x<b.x:a.y<b.y;}
int dis(node a,node b,node c){return abs(a.x-b.x)+abs(a.y-b.y)+abs(a.x-c.x)+abs(a.y-c.y)+abs(b.x-c.x)+abs(b.y-c.y);}
void solve(int l,int r)
{
if(r-l<)
{
for(int i=l;i<r-;i++)for(int j=i+;j<r;j++)for(int k=j+;k<r+;k++)
ansmin=min(ansmin,dis(p[i],p[j],p[k]));return;
}
int mid=(l+r)/,cnt=,be=;solve(l,mid);solve(mid,r);
for(int i=mid;i<=r&&abs(p[i].x-p[mid].x)<ansmin;i++)q[++cnt]=p[i];
for(int i=mid-;i>=l&&abs(p[i].x-p[mid].x)<ansmin;i--)q[++cnt]=p[i];
sort(q+,q++cnt,cmp2);
for(int i=;i<=cnt;i++)
{
while(abs(q[be].y-q[i].y)>=ansmin)be++;
for(int j=be;j<i-;j++)for(int k=j+;k<i;k++)
ansmin=min(ansmin,dis(q[i],q[j],q[k]));
}
}
int main()
{
scanf("%d",&n);
addmin=submin=xmin=ymin=ansmin=<<;
addmax=submax=xmax=ymax=ansmax=-<<;
for(int i=;i<=n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
xmax=max(xmax,p[i].x);ymax=max(ymax,p[i].y);
xmin=min(xmin,p[i].x);ymin=min(ymin,p[i].y);
addmax=max(addmax,p[i].x+p[i].y);addmin=min(addmin,p[i].x+p[i].y);
submax=max(submax,p[i].x-p[i].y);submin=min(submin,p[i].x-p[i].y);
}
ansmax=max(ansmax,addmax-xmin-ymin);ansmax=max(ansmax,xmax+ymax-addmin);
ansmax=max(ansmax,submax-xmin+ymax);ansmax=max(ansmax,xmax-ymin-submin);
sort(p+,p++n,cmp1);solve(,n);
printf("%d\n%d",ansmax*,ansmin);
}

中山纪中集训Day2又是测试(划水)的更多相关文章

  1. 「中山纪中集训省选组D1T1」最大收益 贪心

    题目描述 给出\(N\)件单位时间任务,对于第\(i\)件任务,如果要完成该任务,需要占用\([S_i, T_i]\)间的某个时刻,且完成后会有\(V_i\)的收益.求最大收益. 澄清:一个时刻只能做 ...

  2. 中山纪中集训Day4双是测试(划沝) 九校联考-DL24凉心模拟Day2

    A组T1 锻造 (forging) 1.1 题目背景 勇者虽然武力值很高,但在经历了多次战斗后,发现怪物越来越难打于是开始思考是不是自己平时锻炼没到位,于是苦练一个月后发现......自己连一个史莱姆 ...

  3. 中山纪中集训Day5叒是测试(划淼)

    A组T1 矩阵游戏(game) 九校联考24OI__D1T1 问题描述 LZK发明一个矩阵游戏,大家一起来玩玩吧,有一个N行M列的矩阵.第一行的数字是1,2,…M,第二行的数字是M+1,M+2…2*M ...

  4. 中山纪中集训Day1测试(摸鱼)

    AT3 粉刷匠 Description 赫克托是一个魁梧的粉刷匠,而且非常喜欢思考= = 现在,神庙里有N根排列成一直线的石柱,从1到N标号,长老要求用油漆将这些石柱重新粉刷一遍.赫克托有K桶颜色各不 ...

  5. 「中山纪中集训省选组D4T1」折射伤害 高斯消元

    题目描述 在一个游戏中有n个英雄,初始时每个英雄受到数值为ai的伤害,每个英雄都有一个技能"折射",即减少自己受到的伤害,并将这部分伤害分摊给其他人.对于每个折射关系,我们用数对\ ...

  6. 「中山纪中集训省选组D2T1」书堆 欧拉常数

    题目描述 蚂蚁是勤劳的动物,他们喜欢挑战极限.现在他们迎来了一个难题!蚂蚁居住在图书馆里,图书馆里有大量的书籍.书是形状大小质量都一样的矩形.蚂蚁要把这些书摆在水平桌子的边缘.蚂蚁喜欢整洁的布置,所以 ...

  7. 纪中集训 Day1

    今天早上起来吃饭,发现纪中伙食真的是太差了!!!什么都不热,早餐的面包还好,然后就迎来了美好的早晨= = 早上做一套题,T1T2果断秒,T3一看就是noi原题,还好看过题解会写,然后就愉快的码+Deb ...

  8. 纪中集训 Day 2

    今天(其实是昨天= =)早上起来发现好冷好冷啊= = 吃完饭就准备比赛了,好吧B组难度的题总有一道不知到怎么写QAQ 太弱了啊!!! 蒟蒻没人权啊QAQ 今天第4题不会写,在这里说说吧 题目的意思就是 ...

  9. 纪中集训 Day 0?

    好吧昨天的等到今天才来写,现在超不想刷题,来写下blog吧= = 坐了近10H的火车终于来到了中山市 火车上在看空之境界,等有时间补下动画吧= = 到了宿舍各种不习惯(现在才发现还是母校好QAQ)然后 ...

随机推荐

  1. Python与Golang协程异同

    背景知识 这里先给出一些常用的知识点简要说明,以便理解后面的文章内容. 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定 ...

  2. 【kubernetes】通过rancher2部署k8s

    1. K8S相关介绍 十分钟带你理解Kubernetes核心概念 2. 部署rancher # 更新操作系统软件包 yum update -y # 删除历史容器及数据 docker rm -f $(d ...

  3. Attribute与Property关系

    总的来说,其实是HTML Attribute 与 DOM property之间的关系. 1 什么是Property? JS DOM Object对象有property.一个property可能是不同数 ...

  4. 【JavaWEB SSH】jsp页面传值后台Controller 部分值绑定不上实体类

    //前端ajax代码 1 var oldpassword = $('#old_password').val(); var password = $('#L_pass').val(); var user ...

  5. python 数据类型 常用法方

    python 数据类型 常用法方 upper() 大写 str lower() 小写 str strip() rstrip() lstrip() 去除字符两边的空格 去右边 左边空白 str repl ...

  6. Android笔记(六十四) android中的动画——补间动画(tweened animation)

    补间动画就是只需要定义动画开始和结束的位置,动画中间的变化由系统去补齐. 补间动画由一下四种方式: 1.AplhaAnimation——透明度动画效果 2.ScaleAnimation ——缩放动画效 ...

  7. docker到底比LXC多了些什么

    看似docker主要的OS级虚拟化操作是借助LXC, AUFS只是锦上添花.那么肯定会有人好奇docker到底比LXC多了些什么.无意中发现 stackoverflow 上正好有人问这个问题, 回答者 ...

  8. golang读写文件的几种方式

    golang中处理文件有很多种方式,下面我们来看看. (1)使用os模块 先来看看如何查看文件属性 package main import ( "fmt" "os&quo ...

  9. 运维开发笔记整理-django日志配置

    运维开发笔记整理-django日志配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Django日志 Django使用python内建的logging模块打印日志,Pytho ...

  10. MongonDB 知识

    配置 vi  mongodb.conf dbpath=/usr/local/mongodb/data/ logpath=/usr/local/mongodb/data/mongodb.log port ...