cf#10-B - Cinema Cashier-暴力+树状数组

http://codeforces.com/contest/10/problem/B

题目大意:

n波人去k*k的电影院看电影。

要尽量往中间坐,往前坐。优先考虑中间


没想到什么好的办法。。xjb暴力贪心,用个树状数组辅助一下查询时减轻复杂度。。

复杂度 n*k*k*logk.........n=1000,k=100


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include<stack>
using namespace std;
 
int tm[1005];
const int inf=2147483647;
int tree[105][105*4];
int lowbit(int x)
{return x&(-x);}
void add(int x,int value,int id)
{
	for (int i=x;i<=100;i+=lowbit(i))
		tree[id][i]+=value;
} 
int get(int x,int id)
{
	int sum=0;
	for (int i=x;i;i-=lowbit(i))
		sum+=tree[id][i];
	return sum;
}

int main()
{
	int i ,j,k;
	int n,m;
	cin>>n>>m;
	for (i=1;i<=n;i++)
	{
		scanf("%d",&tm[i]);
	} 
	
	int xx=ceil(1.0*m/2);
	int yy=xx;
	
	
	for (k=1;k<=n;k++)
	{
		int num=tm[k];
		int ans=inf;
		int minx,miny=1;		
		for (i=1;i<=m;i++)
		{
			for (j=1;j+num-1<=m;j++)
			{
				int ret=get(j+num-1,i)-get(j-1,i);
				if (ret!=0)continue;
				int tmp=abs(xx-i)*num;
				if (j>=yy)
					tmp+=  (j+j+num-1)*(num)/2-num*yy;
				else
					if (j+num-1<=yy)
						tmp+=num*yy-(j+j+num-1)*(num)/2;
					else
						tmp+=yy*(yy-j+1)-(j+yy)*(yy-j+1)/2+(j+num-1+yy+1)*(j+num-1-(yy+1)+1)/2-yy*(j+num-1-(yy+1)+1);
					if (tmp<=ans)
					{
						if (tmp<ans)
						{
							ans=tmp;
							minx=i;
							miny=j;
						}
						else
						{
							if (i<minx)
							{
								minx=i,miny=j;
							}
							else
								if (i==minx)
								{
									if (j<miny)
									{
										miny=j;
									}
								}
						}
					}
					
					
			}
		}
		if (ans!=inf)
		{
			printf("%d %d %d\n",minx,miny,miny+num-1);
			for (i=miny;i<=miny+num-1;i++)
				add(i,1,minx);
		}
		else
		printf("-1\n");
	}
	
	return 0;
	
}


你可能感兴趣的:(cf#10-B - Cinema Cashier-暴力+树状数组)