Zhongshan Jizhong training is Day2 test (the water)

A 组 T1 bzoj 2674 Attack

Description

chnlich I love to play the Three Kingdoms game, and like to use some of the strategies surprise. Now, he wants to begin the journey to conquer the world. His enemy cities N and N prefect, N N cities can be viewed as points on a two dimensional plane. N cities numbered 0,1,2, ......, N-1. The coordinates of the i-th city is (Xi, Yi), the ability to guard the city prefect of the value of Zi.

Each time a chnlich choose sides parallel to the axis of the rectangular area, and wherein surprise Prefecture ability value of K small city (city and after the surprise still Prefecture).

However, his enemies often secretly exchange prefect two cities, to prevent weakness was chnlich found.

Now, chnlich wanted to know his enemy's ability to value each time surprise.

Input

The first line of input contains two integers N, M, N represents the number of cities and prefect, M is M events happens next.

The second input to the first line of row 1 + N, each containing three integers, the i + 2 row three sequentially represents an integer number of the city i Xi, Yi, Zi, as defined problem.

Second row to the N + 2 N + M + 1 input lines, each line has two possible forms:

The first

QUERY x0 y0 x1 y1 k

Represents a relative vertex chnlich query (x0, y0), (x1, y1) of the rectangle, the k value is too small capacity

The ability to keep the value.

The second

SWAP x y

Represents chnlich enemies exchanged numbers x and y two cities Prefecture.

Output

For each QUERY, output line.

There is a small capacity of the k value if not prefect, output "It does not exist." (Without the quotes).

Otherwise, output an integer value of the capacity of the rectangle represents the k value is smaller capacity prefect.

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
to 100% of the data, N <= 60000, M < = 10000,0 <= Xi, Yi, Zi <= 10 ^ 9, k <= 10 ^ 9, to ensure that all operations are valid.

analysis

Reason, positive solution of this problem is cancer. BUT, it was cheap hand on OJ, then turned into a time 1s 10s! ! ! ! ! ! ! !

Pair, is 10 seconds

Each point directly to sort by weight, when asked O (n) on the line scan again encounter is recorded until the first number of the k-th like, switching exchange directly within the rectangle.

Complexity is O (nm)

Note that, the upper left and lower right rectangle may give two endpoints, may give the lower left and upper right of the two endpoints.

Code:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,q[60005],ma[60005];char ch[5];
struct node{int x,y,z;}p[60005];
bool cmp(int a,int b){return p[a].z<p[b].z;}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z),q[i]=i;
    sort(q+1,q+1+n,cmp);
    for(int i=1;i<=n;i++)ma[q[i]]=i;
    for(int i=1;i<=m;i++)
    {
        scanf("%s",ch+1);
        if(ch[1]=='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[1]=='Q')
        {
            int x1,y1,x2,y2,k,cnt=0,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=1;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[125][125];mar(){memset(a,0,sizeof a);}
    inline mar operator *(const mar &b)const
    {
        mar c;
        for(int i=1;i<=m;i++)for(int k=1;k<=m;k++)for(int j=1;a[i][k]>=1e-11&&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=0;i<=r;i++)for(int j=1;j<=q;j++)
    {
        B.a[id(i,j)][id(i+1,j+1)]=p;
        B.a[id(i,j)][m]=i;//计算每个状态对答案的贡献
        if(j>1)B.a[id(i,j)][id(0,j-1)]=1.0-p;
    }
    int k1=n+1;for(int i=1;i<=m;i++)C.a[i][i]=1.0;//n+1是因为dp[n][j][k]的答案之前没统计到,要多乘一次来统计。
    while(k1){if(k1&1)C=B*C;B=B*B;k1/=2;}
    A.a[1][id(0,q)]=1.0;A=A*C;
    
    return A.a[1][m]>double(s);
}
int main()
{
    scanf("%d%d%d%d",&n,&r,&q,&s);
    double l1=0,r1=1,ans=0;m=(r+1)*q+1;//m就是那个来存答案的编号
    if(pan(r1)<1e-7){printf("Impossible.");return 0;}
    while(r1-l1>2*1e-7)
    {
        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[100005],q[100005];
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<15)
    {
        for(int i=l;i<r-1;i++)for(int j=i+1;j<r;j++)for(int k=j+1;k<r+1;k++)
        ansmin=min(ansmin,dis(p[i],p[j],p[k]));return;
    }    
    int mid=(l+r)/2,cnt=0,be=1;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-1;i>=l&&abs(p[i].x-p[mid].x)<ansmin;i--)q[++cnt]=p[i];
    sort(q+1,q+1+cnt,cmp2);
    for(int i=3;i<=cnt;i++)
    {
        while(abs(q[be].y-q[i].y)>=ansmin)be++;
        for(int j=be;j<i-1;j++)for(int k=j+1;k<i;k++)
        ansmin=min(ansmin,dis(q[i],q[j],q[k]));
    }
}
int main()
{
    scanf("%d",&n);
    addmin=submin=xmin=ymin=ansmin=1<<30;
    addmax=submax=xmax=ymax=ansmax=-1<<30;
    for(int i=1;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+1,p+1+n,cmp1);solve(1,n);
    printf("%d\n%d",ansmax*2,ansmin);
}

 

Guess you like

Origin www.cnblogs.com/firecrazy/p/11296213.html