中南oj 2019年1月月赛 Hello 2019! (Div1+Div2) 题解

A: Rikka和Galgame

不会待补

B: 假装是区间众数

思路:莫队算法,离线给所有区间排序,然后按顺序求答案即可,复杂度n^1.5

// res[ i ]=x 含义为有x个数出现了 i 次

#include
#define db double
using namespace std;
const int maxn=1e5+10;
int a[maxn],b[maxn],vis[maxn],ans[maxn],block;
int res[maxn],mx;
struct node
{
	int l,r,id;
	bool operator<(const node&t)const
	{
		if(l/block==t.l/block)
		return r=c[i].l;j--)
		up(j,1);
		for(int j=q+1;j<=c[i].r;j++)
		up(j,1);
		for(int j=q;j>c[i].r;j--)
		up(j,-1);
		ans[c[i].id]=mx;
		p=c[i].l,q=c[i].r;
	}
	for(int i=1;i<=Q;i++)
	printf("%d\n",ans[i]);
}

C: 上杉绘梨衣的告别(一)——时光南站

思路:暴力枚举len即可(每0.5枚举一次),然后用二分查找出最近的算答案即可,复杂度len*m*log(n)

#include
#define db double
using namespace std;
const int maxn=1e5+10;
int p[305],d[305],len,m,n;
db ans,pos,b[305];
void ss(db xx)
{
	for(int i=1;i<=n;i++)
	b[i]=d[i]+xx;
	db res=0;
	for(int i=1;i<=m;i++)
	{
		int x=lower_bound(b+1,b+1+n,p[i])-b;
		if(x>n)x--;
		else if(x==0)x++;
		db tmp=fabs(b[x]-p[i]);
		if(b[x]>p[i])
		{
			if(x!=1)
			tmp=min(tmp,fabs(b[x-1]-p[i]));
		}
		else if(b[x]ans)ans=res,pos=xx;
}
int main()
{
	while(cin>>len)
	{
		cin>>m;
		for(int i=1;i<=m;i++)
		cin>>p[i];
		cin>>n;
		for(int i=2;i<=n;i++)
		cin>>d[i];
		ans=0,pos=0;
		for(int i=0;i<=len-d[n];i++)
		{
			ss(i);
			if(i!=len-d[n])
			ss(0.5+i);
		}
		printf("%.3lf %.3f\n",pos,ans);
	}
}

D: 上杉绘梨衣的告别(二)——项链

不会待补

E: 喜闻乐见的逆序对

思路:重点讲这题(其实很水的),举个例子,五个数:1 2 3 4 5,贡献分别为 3 2 0 0 0,我先从大到小枚举这5个数,5的贡献是0,从空集插入一个5,4的贡献也为0,那么4就插到集合第0个数的后面,集合有两个数 4->5,3同理,插入后 3->4->5,接下来2的贡献为2,那么显然把2插入集合第二个数的后面,即3->4->2->5,1就插入到第三个数的后面,所以答案是 3 4 2 1 5。

ok,思路是不是很清晰了?不过还是没有完全解决这个问题,普通插入n*n的复杂度肯定不行,动态插入怎么搞?这时就要献出treap了(不会可以先学,顺便a了这个题,这题用到的treap十分简单),完美的用n*logn复杂度解决掉动态插入问题。

#include
using namespace std;
const int maxn=1e5+10;
struct node
{
	int num,v;
	bool operator<(const node&t)const
	{
		return num>t.num;
	}
}a[maxn];
int cnt,ans[maxn];
struct Node *null;
struct Node
{
	Node *ch[2];
	int r;
	int v;
	int s;
	Node(int v):v(v){ch[0]=ch[1]=null;r=rand();s=1;}
	void maintain()
	{
		s=1;
		s+=ch[0]->s;
		s+=ch[1]->s;
	}
};
void rotate(Node* &o,int d)
{
	Node *k=o->ch[d^1];o->ch[d^1]=k->ch[d];
	k->ch[d]=o;o->maintain();k->maintain();
	o=k;
}
void insert(Node* &o,int x,int k)
{
	if(o==null) o=new Node(x);
	else
	{
		int d=(k<=(o->ch[0]->s)?0:1);
		if(d==1)k=k-o->ch[0]->s-1;
		insert(o->ch[d],x,k);
		if(o->ch[d]->r>o->r)rotate(o,d^1);
	}
	o->maintain();
}

void dfs(Node* o)
{
	if(o==null)return;
	dfs(o->ch[0]);
	ans[++cnt]=o->v;
	dfs(o->ch[1]);
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i].num);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i].v);
	sort(a+1,a+1+n);
	
	null=new Node(0);
	null->s=0;
	Node *root=null;
	
	for(int i=1;i<=n;i++)
	insert(root,a[i].num,a[i].v);
	
	dfs(root);
	for(int i=1;i

 

你可能感兴趣的:(比赛----中南div1题解,中南oj,月赛题解)