• 8.3总结


    8.3总结

    得分

    0+45+50

    惊险刺激

    8:30的时候我估计能拿250分

    10:30的时候我估计我会爆零

    一开始以为会做T1T3

    结果打出来都不对

    赛后发现反而是T2最简单

    其实T1暴力能过

    T1

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

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

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

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

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

    Time Limits: 10000 ms

    欺诈题

    NM可以过

    先按Z排序,每次询问找到第k个在矩形内的城市就是答案了

    T2

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

    若没有通过这个关卡,将会失去1条命,并进入下一个关卡。当没有生命或没有未挑战过的关卡时,游戏结束,得到的分数为每关得到的分数的总和。

    由于 chnlich 好久不玩这个游戏了,每条命通过每个关卡的概率均为p(0<=p<=1),原先 chnlich 的最高分纪录是 S。现在 chnlich 想要知道,当 p 至少为多少时,chnlich 期望获得的总分数能够超过原先的最高分。

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

    一眼二分加矩乘

    方程是

    [f[i+1][min(j+1,Q)][min(k+1,R)]+=f[i][j][k]*p;\ f[i+1][j-1][0]+=f[i][j][k]*(1-p);\ ans+=f[i][j][k]*p*(min(k+1,R)); ]

    一开始我以为那个ans不能矩乘,实际上是可以的

    T3

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

    这些炸弹非常特殊 , 只要同时拆除其中的三个炸弹 , 所有炸弹就都不会爆炸了。由于各个情报站联络需要代价 , 拆除炸弹需要花费的总代价为这些炸弹两两之间的曼哈顿距离和。现在 A 国的指挥部门找到了你 , 希望知道可能需要的最大代价和最小代价 。

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

    先考虑只要选择两个点的情况,令 Xmax 表示两个点中 X 坐标较大的点的 X 坐标,Xmin
    表示两个点中 X 坐标较小的点的 X 坐标,Ymax,Ymin 同理。则答案即为
    Xmax-Xmin+Ymax-Ymin。我们先计算最大值。考虑最大值的分布,显然我们只要选出使
    Xmax+Ymax,-Xmin-Ymin,Xmax-Ymin,-Xmin+Ymax 这四个表达式值最大的点暴力即可。
    然后计算最小值。若不考虑 Xmin=Xmax 或 Ymin=Ymax 这些极端情况,两个点的位置情况
    只有两种(左下,左上),是对称的,我们只考虑其中的一种情况。以第一个点在第二个点左
    下方为例。则第一个点的坐标为(Xmin,Ymin)。显然,我们要查找的是 X>Xmin 且 Y>Ymin
    且 X+Y 最小的点。我们可以按 X 轴从大到小枚举,保证 X>Xmin,按 Y 轴坐标维护一棵线
    段树,记录区间 X+Y 最小的值,在每个点处只要在线段树中查询[Ymin,+ ∞)中的 X+Y 最小
    值,更新答案,然后插入点(Xmin,Ymin)即可。时间复杂度 O(NlogN)。
    接下来考虑三个点的情况。我们考虑三个点两两之间的曼哈顿距离和的实质。通过画图,
    我们容易发现,问题的实质是求能包含这三个点的最小矩形的周长,即
    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 的点在左上方(即该点在 3 个点中
    的-Xmin+Ymax 最小),设另外两个点分别为(Xmax,Y)和(X,Ymin)。我们维护一棵线段树,
    维护在 X 在 i 处时首先从下方往上方依次枚举每个点作为左上角,我们使用线段树维护所有
    (X,Ymin)节点的 Xmax-Ymin 的最大值。每次枚举一个点,首先查询它(Xmin,+ ∞)中的
    Xmax-Ymin 的最小值更新答案,然后将它作为可能的 Xmax 更新线段树在(-∞ ,Xmin)中的
    Xmax-Ymin,然后把自己作为可能的 Ymin 更新线段树在这个点上的最大 Y 值,就可以完美
    解决情况①,时间复杂度 O(NlogN)。
    对于情况②,我们枚举中间的点,然后计算四个方向上离它最近的节点,这个即为两个
    点求最近曼哈顿距离的情况。计算对角方向两个最近点的距离和并更新答案即可。时间复杂
    度仍为 O(NlogN)。
    这题同样可以使用分治算法解决,时间复杂度仍为 O(NlogN)。

    By Bomb解题报告.pdf

    ~有很多小错误~

    有几个地方需要注意

    1. 把全部点旋转时,点(x,y)变为(-y,x)
    2. 解决情况①时,更新单点的时候不能更新答案,见代码
    3. 对于情况②,为了防止重合的点重复计算,我们用1~i-1的点更新i的一个方向,用i+1~n的点更新i的对角方向
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define INF 1000000000
    using namespace std;
    
    struct kk
    {
    	int x,y,rank;
    };
    
    struct qy
    {
    	int x,y,ans,tag,ans2;
    };
    
    int n,i,j,k,ans1,ans2,fx;
    kk a[100005],b[100005];
    int t1[100005],t2[100005];
    qy tree[400005],treee[400005];
    int sel[9];
    int mi[5][100005];
    
    int find1(int x)
    {
    	int l=1,r=t1[0],mid=(l+r)/2;
    	while (l<r)
    	{
    		if (t1[mid]<x) l=mid+1;
    		else r=mid;
    		mid=(l+r)/2;
    	}
    	return mid;
    }
    
    int find2(int x)
    {
    	int l=1,r=t2[0],mid=(l+r)/2;
    	while (l<r)
    	{
    		if (t2[mid]<x) l=mid+1;
    		else r=mid;
    		mid=(l+r)/2;
    	}
    	return mid;
    }
    
    int comp(kk a,kk b)
    {
    	return ((a.x>b.x)||((a.x==b.x)&&(a.y>b.y)));
    }
    
    void clear(int k,int l,int r)
    {
    	tree[k].x=tree[k].y=tree[k].tag=INF;
    	tree[k].ans=INF;
    	if (l!=r)
    	{
    		int mid=(l+r)/2;
    		clear(k*2,l,mid);
    		clear(k*2+1,mid+1,r);
    	}
    }
    
    void clear2(int k,int l,int r)
    {
    	treee[k].x=treee[k].y=treee[k].tag=INF;
    	treee[k].ans=INF;
    	treee[k].ans2=-INF;
    	if (l!=r)
    	{
    		int mid=(l+r)/2;
    		clear2(k*2,l,mid);
    		clear2(k*2+1,mid+1,r);
    	}
    }
    
    void pushdown(int k,int l,int r)
    {
    	if (l!=r)
    	{
    		tree[k*2].ans=min(tree[k*2].ans,tree[k*2].x+tree[k].tag);
    		tree[k*2].tag=min(tree[k*2].tag,tree[k].tag);
    		tree[k*2+1].ans=min(tree[k*2+1].ans,tree[k*2+1].x+tree[k].tag);
    		tree[k*2+1].tag=min(tree[k*2+1].tag,tree[k].tag);
    	}
    	tree[k].tag=INF;
    }
    
    void update(int k,int l,int r)
    {
    	tree[k].x=min(tree[k*2].x,tree[k*2+1].x);
    	tree[k].y=min(tree[k*2].y,tree[k*2+1].y);
    	tree[k].ans=min(tree[k*2].ans,tree[k*2+1].ans);
    }
    
    int query(int k,int l,int r,int x,int y)
    {
    	pushdown(k,l,r);
    	if ((l<=y)&&(r>=x))
    	{
    		if ((l>=x)&&(r<=y))
    		{
    			return tree[k].ans;
    		}
    		int mid=(l+r)/2;
    		return min(query(k*2,l,mid,x,y),query(k*2+1,mid+1,r,x,y));
    	}
    	return INF;
    }
    
    int query2(int k,int l,int r,int x,int y)
    {
    	if ((l<=y)&&(r>=x))
    	{
    		if ((l>=x)&&(r<=y))
    		{
    			return treee[k].ans;
    		}
    		int mid=(l+r)/2;
    		return min(query2(k*2,l,mid,x,y),query2(k*2+1,mid+1,r,x,y));
    	}
    	return INF;
    }
    
    int query3(int k,int l,int r,int x,int y)
    {
    	if ((l<=y)&&(r>=x))
    	{
    		if ((l>=x)&&(r<=y))
    		{
    			return treee[k].ans2;
    		}
    		int mid=(l+r)/2;
    		return max(query3(k*2,l,mid,x,y),query3(k*2+1,mid+1,r,x,y));
    	}
    	return -INF;
    }
    
    void modify1(int k,int l,int r,int x,int y)
    {
    	pushdown(k,l,r);
    	if (l==r)
    	{
    		tree[k].x=min(tree[k].x,y);
    	}
    	else
    	{
    		int mid=(l+r)/2;
    		if (x<=mid)
    			modify1(k*2,l,mid,x,y);
    		else
    			modify1(k*2+1,mid+1,r,x,y);
    		tree[k].x=min(tree[k*2].x,tree[k*2+1].x);//这里不能更新ans,因为旧的y都在x右边 
    	}
    }
    
    void modify2(int k,int l,int r,int x,int y,int z)
    {
    	pushdown(k,l,r);
    	if ((l<=y)&&(r>=x))
    	{
    		if ((l>=x)&&(r<=y))
    		{
    			tree[k].ans=min(tree[k].ans,tree[k].x+z);//必须这样打,因为是用这个z跟以前的x匹配 
    			tree[k].tag=min(tree[k].tag,z);
    			return;
    		}
    		int mid=(l+r)/2;
    		modify2(k*2,l,mid,x,y,z);
    		modify2(k*2+1,mid+1,r,x,y,z);
    		update(k,l,r);
    	}
    }
    
    void modify3(int k,int l,int r,int x,int y)
    {
    	if (l==r)
    	{
    		treee[k].ans=min(treee[k].ans,y);
    		treee[k].ans2=max(treee[k].ans2,y);
    	}
    	else
    	{
    		int mid=(l+r)/2;
    		if (x<=mid)
    			modify3(k*2,l,mid,x,y);
    		else
    			modify3(k*2+1,mid+1,r,x,y);
    		treee[k].ans=min(treee[k*2].ans,treee[k*2+1].ans);
    		treee[k].ans2=max(treee[k*2].ans2,treee[k*2+1].ans2);
    	}
    }
    
    void does()
    {
    	int i,j,s1,s2;
    	for (i=1;i<=n;i++) b[i].rank=i;
    	t1[0]=0;
    	for (i=1;i<=n;i++)
    		t1[++t1[0]]=a[i].x;
    	sort(t1+1,t1+1+t1[0]);
    	for (i=1;i<=n;i++)
    		b[i].x=find1(a[i].x);
    	t2[0]=0;
    	for (i=1;i<=n;i++)
    		t2[++t2[0]]=a[i].y;
    	sort(t2+1,t2+1+t2[0]);
    	for (i=1;i<=n;i++)
    		b[i].y=find2(a[i].y);
    	sort(b+1,b+1+n,comp);
    	
    	clear(1,1,n);
    	for (i=1;i<=n;i++)
    	{
    		s1=query(1,1,n,b[i].y,n);
    		ans2=min(ans2,s1-t1[b[i].x]-t2[b[i].y]);
    		modify1(1,1,n,b[i].y,t1[b[i].x]);
    		modify2(1,1,n,1,b[i].y-1,t2[b[i].y]);
    	}	
    }
    
    void does2()
    {
    	for (i=1;i<=n;i++) b[i].rank=i;
    	t1[0]=0;
    	for (i=1;i<=n;i++)
    		t1[++t1[0]]=a[i].x;
    	sort(t1+1,t1+1+t1[0]);
    	for (i=1;i<=n;i++)
    		b[i].x=find1(a[i].x);
    	t2[0]=0;
    	for (i=1;i<=n;i++)
    		t2[++t2[0]]=a[i].y;
    	sort(t2+1,t2+1+t2[0]);
    	for (i=1;i<=n;i++)
    		b[i].y=find2(a[i].y);
    	sort(b+1,b+1+n,comp);
    	
    	clear2(1,1,n);
    	fx++;
    	for (i=1;i<=n;i++)
    	{
    		mi[fx][b[i].rank]=query2(1,1,n,b[i].y,n)-t1[b[i].x]-t2[b[i].y];
    		modify3(1,1,n,b[i].y,t1[b[i].x]+t2[b[i].y]);
    	}
    	clear2(1,1,n);
    	fx++;
    	for (i=n;i>=1;i--)
    	{
    		mi[fx][b[i].rank]=t1[b[i].x]+t2[b[i].y]-query3(1,1,n,1,b[i].y);
    		modify3(1,1,n,b[i].y,t1[b[i].x]+t2[b[i].y]);
    	}
    }
    
    int js(int x,int y,int z)
    {
    	return (max(max(a[x].x,a[y].x),a[z].x)-min(min(a[x].x,a[y].x),a[z].x)+max(max(a[x].y,a[y].y),a[z].y)-min(min(a[x].y,a[y].y),a[z].y));
    }
    
    int main()
    {
    	freopen("read.in","r",stdin);
    	ans1=0;
    	ans2=100000000;
    	scanf("%d",&n);
    	for (i=1;i<=n;i++)
    	{
    		scanf("%d%d",&a[i].x,&a[i].y);
    	}
    	for (i=1;i<=8;i++)
    	sel[i]=1;
    	for (i=1;i<=n;i++)
    	{
    		if (a[sel[1]].x+a[sel[1]].y<a[i].x+a[i].y) sel[1]=i;
    		if (a[sel[2]].x-a[sel[2]].y<a[i].x-a[i].y) sel[2]=i;
    		if (-a[sel[3]].x+a[sel[3]].y<-a[i].x+a[i].y) sel[3]=i;
    		if (-a[sel[4]].x-a[sel[4]].y<-a[i].x-a[i].y) sel[4]=i;
    		if (a[sel[5]].x<a[i].x) sel[5]=i;
    		if (-a[sel[6]].x<-a[i].x) sel[6]=i;
    		if (a[sel[7]].y<a[i].y) sel[7]=i;
    		if (-a[sel[8]].y<-a[i].y) sel[8]=i;
    	}
    	for (i=1;i<=8;i++)
    	{
    		for (j=i+1;j<=8;j++)
    		{
    			for (k=j+1;k<=8;k++)
    			{
    				if ((sel[i]!=sel[j])&&(sel[i]!=sel[k])&&(sel[j]!=sel[k]))
    				ans1=max(ans1,js(sel[i],sel[j],sel[k]));
    			}
    		}
    	}
    	does();
    	for (i=1;i<=n;i++)
    	{
    		swap(a[i].x,a[i].y);
    		a[i].x=-a[i].x;
    	}
    	does();
    	for (i=1;i<=n;i++)
    	{
    		swap(a[i].x,a[i].y);
    		a[i].x=-a[i].x;
    	}
    	does();
    	for (i=1;i<=n;i++)
    	{
    		swap(a[i].x,a[i].y);
    		a[i].x=-a[i].x;
    	}
    	does();
    	for (i=1;i<=n;i++)
    	{
    		swap(a[i].x,a[i].y);
    		a[i].x=-a[i].x;
    	}
    	does2();
    	for (i=1;i<=n;i++)
    	{
    		swap(a[i].x,a[i].y);
    		a[i].x=-a[i].x;
    	}
    	does2();
    	for (i=1;i<=n;i++)
    	{
    		ans2=min(ans2,mi[1][i]+mi[2][i]);
    		ans2=min(ans2,mi[3][i]+mi[4][i]);
    		if (ans2==0)
    		{
    			ans2=ans2;
    		}
    	}
    	printf("%d
    %d",ans1*2,ans2*2);
    	
    }
    

    丑死了

  • 相关阅读:
    MS SQL Server2012中的TRY_CONVERT函数
    MS SQL Server2012中的CONCAT函数
    查询数据库大小
    显示数据与存储方式
    Windows 8 安装之后怎样更改产品码
    IIS SubStatus Codes
    MS SQL Server Quarter Function
    程序中处理一对多的数据
    找出字符串中所有数字
    BOOTMGR is missing
  • 原文地址:https://www.cnblogs.com/leason-lyx/p/11293740.html
Copyright © 2020-2023  润新知