zoukankan      html  css  js  c++  java
  • [JOI 2020 Final] 長いだけのネクタイ 题解

    [JOI 2020 Final] 長いだけのネクタイ

    Description

    在这里插入图片描述

    Input

    在这里插入图片描述

    Output

    在这里插入图片描述

    Sample Input

    样例 1 输入:
    3
    4 3 7 6
    2 6 4

    样例 2 输入:
    5
    4 7 9 10 11 12
    3 5 7 9 11

    Sample Output

    样例 1 输出:
    2 2 1 1
    在这里插入图片描述
    样例 2 输出:
    4 4 3 2 2 2

    Data Constraint

    在这里插入图片描述

    题解

    好不容易模拟赛有一道签到题
    首先可以显然证明,在拿掉一个领带后,将剩下的领带长度从大到小排序,把人本来戴着的领带长度从小到大排序,然后一一对应来取(max(0,a[i]-b[i]))是可以使最大值最小的
    然后我们就可以每次都这样做,于是可以得到一个(O(n^2 log n))的算法,只能拿到50分
    显然以上算法浪费了很多的操作,我们知道将(n+1)个领带排好序后,取一个领带出来,那这个领带左边的(也就是比它长的)贡献是不会受到影响的
    所以我们可以写两个线段树,一个统计排序后的(max(0,a[i]-b[i]))的区间最大值(max1),一个统计排序后的(max(0,a[i+1]-b[i]))的区间最大值(max2)
    然后找到拿走的领带在排序后的位置(num),查询这个点左边的(max1)和右边的(max2)再取较大的那个即可,复杂度(O(n log n))轻松通过
    当然也可以记录前缀最大值和后缀最大值然后进行相同的操作,复杂度(O(n))

    CODE(线段树法)

    #include<cstdio>
    #include<string>
    #include<algorithm>
    #define R register int
    #define N 200005
    #define ll long long
    using namespace std;
    int n,tree1[N<<2],tree2[N<<2],num[N],c1[N],c2[N],b[N];
    struct arr{int x,id;}a[N];
    int max(int a,int b) {return a>b?a:b;}
    int min(int a,int b) {return a<b?a:b;}
    void read(int &x)
    {
    	x=0;int f=1;char ch=getchar();
    	while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
    	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();x*=f;
    }
    bool cmp(arr x,arr y) {return x.x>y.x;}
    bool cmp1(int x,int y) {return x>y;}
    void build1(int u,int l,int r)
    {
    	if (l==r) {tree1[u]=c1[l];return;}
    	int mid=l+r>>1;build1(u<<1,l,mid);build1(u<<1|1,mid+1,r);
    	tree1[u]=max(tree1[u<<1],tree1[u<<1|1]);
    }
    void build2(int u,int l,int r)
    {
    	if (l==r) {tree2[u]=c2[l];return;}
    	int mid=l+r>>1;build2(u<<1,l,mid);build2(u<<1|1,mid+1,r);
    	tree2[u]=max(tree2[u<<1],tree2[u<<1|1]);
    }
    int find1(int u,int l,int r,int x,int y)
    {
    	if (l>=x && r<=y) return tree1[u];
    	int mid=l+r>>1,res=0;
    	if (x<=mid) res=max(res,find1(u<<1,l,mid,x,y));if (y>mid) res=max(res,find1(u<<1|1,mid+1,r,x,y));
    	return res;
    }
    int find2(int u,int l,int r,int x,int y)
    {
    	if (l>=x && r<=y) return tree2[u];
    	int mid=l+r>>1,res=0;
    	if (x<=mid) res=max(res,find2(u<<1,l,mid,x,y));if (y>mid) res=max(res,find2(u<<1|1,mid+1,r,x,y));
    	return res;
    }
    int main()
    {
    	read(n);
    	for (R i=1;i<=n+1;++i)
    		read(a[i].x),a[i].id=i;
    	for (R i=1;i<=n;++i)
    		read(b[i]);
    	sort(a+1,a+1+n+1,cmp);sort(b+1,b+1+n,cmp1);
    	for (R i=1;i<=n+1;++i)
    		num[a[i].id]=i;
    	for (R i=1;i<=n;++i)
    		c1[i]=max(a[i].x-b[i],0),c2[i]=max(a[i+1].x-b[i],0);
    	build1(1,1,n);build2(1,1,n);
    	for (R i=1;i<=n+1;++i)
    	{
    		if (num[i]==1) printf("%d ",find2(1,1,n,1,n));
    		else if (num[i]==n+1) printf("%d ",find1(1,1,n,1,n)); 
    		else printf("%d ",max(find1(1,1,n,1,num[i]-1),find2(1,1,n,num[i],n)));
    	}
    	printf("
    ");
    	return 0;
    }
    
  • 相关阅读:
    CentOS 7安装配置FTP服务器
    Python验证码
    Eclipse快捷键
    mybatis中的#和$的区别
    spring framework 各版本源码下载地址
    maven的pom.xml文件标签含义
    maven学习笔记
    (转)C#调用非托管Win 32 DLL
    (转)读取XML数据到treeView中
    SpringSecurity学习二----------实现自定义登录界面
  • 原文地址:https://www.cnblogs.com/CMC-YXY/p/15031733.html
Copyright © 2011-2022 走看看