Tyvj Q1033(线性扫描)

Q1033 - Unit9 - 智力值

From Admin    Normal (OI)
总时限:5s    内存限制:128MB    代码长度限制:64KB

描述 Description

WJ是个很聪明的人,他有一个智力值。 
和比他聪明的人(智力值大于WJ)辩论一次智力值会+2。
和比他笨的人(智力值小于等于WJ)辩论一次智力会+1。
然后每个人只能辩论一次。安排一个辩论顺序。使得辩论完后WJ的智商最高。

输入格式 InputFormat

第一行包含两个正整数n和k,表示要和WJ辩论的人数,以及WJ的初始智力值。
第二行包含n个正整数,表示这n个人的智力值。

输出格式 OutputFormat

第一行包含一个正整数,表示WJ最终智力值的最大值。

样例输入 SampleInput [复制数据]

5 91
88 90 92 94 98

样例输出 SampleOutput [复制数据]

99

数据范围和注释 Hint

数据范围:
   1<=n<=500 智力值范围<=1000

每次贪心贪比他聪明的人中最不聪明的



const
   maxn=5000;
var
   n,i,j,now,tot:longint;
   a:array[1..maxn] of longint;
procedure qsort(l,r:longint);
var
   i,j,m,p:longint;
begin
   i:=l;
   j:=r;
   m:=a[(l+r) div 2];
   repeat
      while a[i]<m do inc(i);
      while a[j]>m do dec(j);
      if i<=j then
      begin
         p:=a[i];
         a[i]:=a[j];
         a[j]:=p;
         inc(i);
         dec(j);
      end;
   until i>j;
   if (l<j) then qsort(l,j);
   if (i<r) then qsort(i,r);


end;
begin
   read(n,now);
   tot:=0;
   for i:=1 to n do read(a[i]);
   qsort(1,n);

   for i:=1 to n do
   begin
      if (now<a[i]) then inc(now,2)
      else inc(tot);
   end;
   writeln(tot+now);



end.

Tyvj P2064(点的向上维护)

P2064 - 「Poetize10」能量获取

From lydliyudong    Normal (OI)
总时限:10s    内存限制:128MB    代码长度限制:64KB

描述 Description

“封印大典启动,请出Nescafe魂珠!”随着圣主applepi一声令下,圣剑护法rainbow和魔杖护法freda将Nescafe魂珠放置于封印台上。封印台是一个树形的结构,魂珠放置的位置就是根节点(编号为0)。还有n个其它节点(编号1~n)上放置着封印石,编号为i的封印石需要从魂珠上获取Ei的能量。能量只能沿着树边从魂珠传向封印石,每条边有一个能够传递的能量上限Wi,魂珠的能量是无穷大的。作为封印开始前的准备工作,请你求出最多能满足多少颗封印石的能量需求?
注意:能量可以经过一个节点,不满足它的需求而传向下一个节点。每条边仅能传递一次能量。

输入格式 InputFormat

第一行一个整数n,表示除根节点之外其它节点的数量。
接下来n行,第i+1行有三个整数Fi、Ei、Wi,分别表示i号节点的父节点、i号节点上封印石的能量需求、连接节点i与Fi的边最多能传递多少能量。

样例输入 SampleInput [复制数据]

4
0 3 2
0 100 100
1 1 1
2 75 80

样例输出 SampleOutput [复制数据]

2

数据范围和注释 Hint

对于 100% 的数据,满足1<=n<=1000,0<=Fi<=n,0<=Ei,Wi<=100。

时间限制 TimeLimitation

各个测试点1s

此题贪心 贪最小的点,易证必最优解

Program energy;
const
   maxn=1000;
var
   n,i,j,ans:longint;
   f,e,w,num,hpos:array[0..maxn] of longint;
procedure swap(var a,b:longint);
var
   t:longint;
begin
   t:=a;a:=b;b:=t;
end;
function max(a,b:longint):longint;
begin
   if a>b then exit(a) else exit(b);
end;
function min(a,b:longint):longint;
begin
   if a<b then exit(a) else exit(b);
end;
procedure qsort(l,r:longint);
var
   i,j,m,p:longint;
begin
   i:=l;
   j:=r;
   m:=e[(l+r) div 2];
   repeat
      while (e[i]<m) do inc(i);
      while (e[j]>m) do dec(j);
      if (i<=j) then
      begin
         swap(e[i],e[j]);
         swap(f[i],f[j]);
         swap(w[i],w[j]);
         swap(num[i],num[j]);
         inc(i);dec(j);
      end;
   until i>j;
   if (l<j) then qsort(l,j);
   if (i<r) then qsort(i,r);

end;

procedure pour(x:longint);
var
   noww,i,j:longint;
begin
   noww:=maxlongint;
   i:=x;
   while (i<>0) do
   begin
      noww:=min(noww,w[i]);
      i:=hpos[f[i]];
   end;

   if (noww<e[x]) then exit;

   inc(ans);
   i:=x;
   while (i<>0) do
   begin
      dec(w[i],e[x]);
      i:=hpos[f[i]];
   end;
end;
begin
   readln(n);
   for i:=1 to n do
   begin
      read(f[i],e[i],w[i]);
      num[i]:=i;
   end;
   qsort(1,n);
   hpos[0]:=0;
   for i:=1 to n do hpos[num[i]]:=i;


//   for i:=1 to n do write(f[i],' ',e[i],' ',w[i]);

   ans:=0;
   for i:=1 to n do pour(i);
   writeln(ans);

end.

CF 217B(逆向思维-Fibonacci)

这题是逆向思维贪心……当时咋没想到……

本题启示:memset的效率与for一遍差不多,故千万memset导致超时……

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
#define MAXN (1000000+10)
int n,r,minchange=MAXN;
bool ans[MAXN]={0},res[MAXN];
bool flag=0;
int calc()
{
	int tot=0;
	for (int i=2;i<=n;i++) if (!res[i]^res[i-1]) tot++;
	return tot;
}
void relax()
{
/*	for (int i=1;i<=n;i++) cout<<res[i]<<' ';
	cout<<endl;
*/	int now=calc();
	if (!flag||now<minchange)
	{
		flag=1;minchange=now;
		memcpy(ans,res,sizeof(ans));
		return;
	}
	if (now>minchange) return;


	for (int i=2;i<=n;i++)
	{
		if (ans[i]<res[i]) return ;
		if (ans[i]>res[i])
		{
			memcpy(ans,res,sizeof(ans));
			return;
		}
	}
}
bool is_ok(int l,int r)
{
//	memset(res,0,sizeof(res));
	res[1]=1;
	for (int i=n;i>1;i--)
	{
		if (!l||!r) return 0;
		if (r<l) {l=l-r; res[i]=1;}
		else {r-=l; res[i]=0;}
	}
	if (l!=1||r!=1) return 0;
	relax();
	for (int i=2;i<=n;i++) res[i]=!res[i];
	relax();
}
int main()
{
	cin>>n>>r;
	for (int i=1;i<=r;i++)
	{
		flag=is_ok(i,r)|flag;
//1		cout<<i<<endl;
	}
	if (!flag) cout<<"IMPOSSIBLEn";
	else
	{
		cout<<minchange<<'n';
		for (int i=1;i<=n;i++)
		{
			if (ans[i]) printf("T");
			else printf("B");
		}
		printf("n");
	}
//	while (1);
	return 0;
}

BYSBZ 1696(建牛舍)

中位数 贪心 

x,y 分开考虑

显然中间那个点一定最省 

1.

奇数 显然中间那个点一定最省  之后走一步答案必会增加,因此中间和4个方向一定最省,另外4个方向增加是对应2个方向的和

2

偶数

判定整个范围会超时

枚举牛而非整个区间,否则TLE


#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<functional>
#include<algorithm>
#define MAXN (10000 + 10)
#define INF 400000000 + 10
using namespace std;
int x[MAXN],y[MAXN];
int a[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
int node[MAXN][2];
int n;
int sum(int nx,int ny)
{
	int tot=0;
	for (int i=1;i<=n;i++)
	{
		tot+=abs(x[i]-nx)+abs(y[i]-ny);
	}
	return tot;
}
int b(int x,int y)
{
	for (int i=1;i<=n;i++)
		if (node[i][0]==x&node[i][1]==y) return true;
	return false;
}
void find(int &minway,int &ans,int x,int y)
{
	int nowtot=sum(x,y);
	if (nowtot<minway)
	{
		ans=1;
		minway=nowtot;
	}
	else if (nowtot==minway) ans++;

}


int calc()
{
	int m=(1+n)/2;
	if (n%2)
	{
		if (!b(x[m],y[m]))
		{
			printf("%d",sum(x[m],y[m]));
			return 1;
		}
		else
		{
			int minway=INF,ans=0;
			for (int i=0;i<4;i++)
			{
				find(minway,ans,x[m]+a[i][0],y[m]+a[i][1]);
			}
			printf("%d",minway);
			return ans;
		}

	}
	else
	{
		int ans=0;
		for (int i=1;i<=n;i++)
		{
			if (x[m]<=node[i][0]&&node[i][0]<=x[m+1]&&y[m]<=node[i][1]&&node[i][1]<=y[m+1]) ans++;
		}
		ans=(x[m+1]-x[m]+1)*(y[m+1]-y[m]+1)-ans;
		printf("%d",sum(x[m],y[m]));
		return ans;
	}
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%d%d",&x[i],&y[i]);
		node[i][0]=x[i];
		node[i][1]=y[i];
	}
	sort(x+1,x+n+1);
	sort(y+1,y+n+1);
	printf(" %dn",calc());
	return 0;
}

POJ 3575(计算几何与二分-无尽的小数处理)

这题 写了将近半个月……总是在D各种Bug

总的说来-这题最难应该是在精度处理上

1

1

0 0 1

这组数据过了就说明精度处理差不多了……

Program kingdom;
const
   maxn=100;
   maxm=100;
   le=0.000000001;
type
   circle=record
            x,y,r:double;
          end;
var
   s:array[1..maxn,1..1000] of circle;
   n,i,j,k:longint;
   m:array[1..maxn] of longint;
   ans:array[1..maxn,1..4] of double;
   wanted:array[1..maxn] of double;
   b:array[1..maxn] of boolean;
   l,r:double;
function arccos(cosa:double):double;
var
   sina,tana:double;
begin
   if cosa=0 then exit(pi/2);

   sina:=sqrt(1-sqr(cosa));
   tana:=sina/cosa;
   exit(arctan(tana));

end;
function min(a,b:double):double;
begin
   if a<b then exit(a) else exit(b);
end;
function max(a,b:double):double;
begin
   if a>b then exit(a) else exit(b);
end;

function sector(a,r:double):double;
begin
   exit(a*r*r/2);
end;
function triangle(a,r:double):double;
begin
   exit(sin(a)*r*r/2);
end;
function inlside(s:circle;l:double):boolean;
begin
   if (s.x-s.r>l) or (abs(s.x-s.r-l)<le) then exit(true) else exit(false);
end;
function inrside(s:circle;r:double):boolean;
begin
   if (s.x+s.r<r) or (abs(s.x+s.r-r)<le) then exit(true) else exit(false);
end;


function intarea(s:circle;l,r:double):double;
var
   i,j:longint;
   a,a2,s1,s2,s3,s4:double;
   bl,br:boolean;
begin
   if (r<s.x-s.r) or (s.x+s.r<l) then exit(0);
   if (s.x<=l) then
   begin
      a:=arccos((l-s.x)/s.r)*2;
      if (abs(s.x-l)<le) then s1:=0
      else s1:=triangle(a,s.r);
      s2:=sector(a,s.r);


      if s.x+s.r>r then
      begin
         a:=arccos((r-s.x)/s.r)*2;
         s3:=sector(a,s.r);
         s4:=triangle(a,s.r);
         s2:=s2-(s3-s4);

      end;
      exit(s2-s1);
   end
   else
   if (s.x>=r) then
   begin
      a:=arccos((s.x-r)/s.r)*2;
      if (abs(s.x-r)<le) then s1:=0
      else s1:=triangle(a,s.r);
      s2:=sector(a,s.r);

      if s.x-s.r<l then
      begin
         a:=arccos((s.x-l)/s.r)*2;
         s3:=sector(a,s.r);
         s4:=triangle(a,s.r);
         s2:=s2-(s3-s4);


      end;
      exit(s2-s1);

   end
   else
   begin
      bl:=inlside(s,l);
      br:=inrside(s,r);
      if bl and br then exit(pi*s.r*s.r);
      if bl and not(br) then
      begin
         a:=arccos((r-s.x)/s.r)*2;
         s3:=sector(a,s.r)-triangle(a,s.r);
         exit(pi*s.r*s.r-s3);
      end;
      if not(bl) and br then
      begin
         a:=arccos((s.x-l)/s.r)*2;
         s3:=sector(a,s.r)-triangle(a,s.r);
         exit(pi*s.r*s.r-s3);
      end;



      a:=arccos((s.x-l)/s.r)*2;

      a2:=arccos((r-s.x)/s.r)*2;
      s1:=sector(2*pi-a-a2,s.r);
      s2:=triangle(a,s.r)+triangle(a2,s.r);
      exit(s1+s2);



   end;



end;
function place(k:longint;l,r:double):boolean;
var
   tot:double;
   i,j:longint;
begin
   tot:=0;
   for j:=1 to m[k] do
   begin
         tot:=tot+intarea(s[k,j],l,r);
   end;
//   writeln(tot*n,' ',wanted[k]*pi);

   if (abs(tot*n-wanted[k]*pi)<le) then exit(true);
   if (tot*n<(wanted[k]*pi)) then exit(false) else exit(true);
end;
function bsearch(r1,r2:double):double;
var
   m:double;
   i,j,k,num:longint;
   flag:boolean;
begin
   for k:=1 to 60 do
   begin
      flag:=false;
      m:=(r1+r2)/2;
      for i:=1 to n do
         if not b[i] then
         begin
            flag:=flag or place(i,l,m);
            if flag then
            begin
               num:=i;
               break;
            end;
         end;
      if flag then r2:=m else r1:=m;
   end;

   b[num]:=true;
   ans[num,1]:=l;
   ans[num,2]:=r1;

   exit(r1);


end;
begin
  { assign(input,'kingdom.in');
   reset(input);
  } r:=-10000;
   l:=10000;
   read(n);
   fillchar(b,sizeof(b),false);
   fillchar(wanted,sizeof(wanted),0);
   for i:=1 to n do
   begin
      read(m[i]);
      for j:=1 to m[i] do
      begin
         read(s[i,j].x,s[i,j].y,s[i,j].r);
 //        writeln(s[i,j].x,s[i,j].y,s[i,j].r);

         r:=max(r,s[i,j].x+s[i,j].r);
         l:=min(l,s[i,j].x-s[i,j].r);
         wanted[i]:=wanted[i]+sqr(s[i,j].r);

      end;
   end;
   r:=r+1;

   for i:=1 to n do
      l:=bsearch(l,r);

   for i:=1 to n do
   begin
      writeln('4');
      writeln(ans[i,1]:7:7,' 3000');
      writeln(ans[i,1]:7:7,' -3000');
      writeln(ans[i,2]:7:7,' -3000');
      writeln(ans[i,2]:7:7,' 3000');
   end;




//   close(input);
end.

Monster (贪心)

Monster

【题目描述】

明明的手机上有这样一个游戏,有一排n个怪物,每个怪物的血量是mi。现在明明可以射出k个伤害均为p的火球射向某些怪物。当某个火球射到第i个怪物,除了这个怪物会掉血p以外,它左边的第j个怪物(j<=i),也会遭到Max(0, p - (i - j)* (i - j))的溅射伤害。当某个怪物的血量为负的时候,它就死了,但它的尸体已然存在,即其他怪物不会因为它死而改变位置。

明明想用这k 个火球消灭掉所有的怪物,但他同时希望每个火球的伤害p能尽可能的小,这样他才能完美过关。

【输入数据】

第一行两个数 nk (1≤ n ≤ 50000, 1 ≤ k ≤ 100000)。

第二行n个数m1m2,...mn (1 ≤ mi ≤ 109),表示每个怪物的生命值。

【输出数据】

最小的符合要求的p值。

【样例输入】

3 1

1 4 5

【样例输出】

6

【数据范围】

1 ≤ n ≤ 50000, 1 ≤ k ≤100000,1 ≤ mi ≤109

30%的数据,n ≤ 500

贪心+二分 显然 最右边那个妖怪一定是被轰击致死的

Program monster;
const
   INF=1000000000;
var
  n,k,i,j:longint;
  m1,a:array[1..50000] of longint;
procedure sort(l,r:longint);
var
   i,j,m,k2,kn:longint;
begin
   if l=r then
   begin
      writeln(l);
      close(input);
      close(output);
      halt;

   end;

   m:=(l+r) shr 1;
   for i:=1 to n do a[i]:=m1[i];
   k2:=k;
   for i:=n downto 1 do
      if a[i]>0 then
      begin
         kn:=k2;
         dec(k2,a[i] div m);
         a[i]:=a[i] mod m;
         if a[i]>0 then
         begin
            dec(k2);
            dec(a[i],m);
         end;

         if k2<0 then sort(m+1,r);
         kn:=kn-k2;
         j:=i-1;
         while (m-sqr(i-j)>0) and (j>=1) do
         begin
            if (kn*(a[j]-m+sqr(i-j))<0) then a[j]:=0 else
            dec(a[j],kn*(m-sqr(i-j)));
            dec(j);
         end;

      end;
   sort(l,m);


end;
begin
   assign(input,'monster.in');
   assign(output,'monster.out');
   reset(input);
   rewrite(output);

   read(n,k);
   for i:=1 to n do
   begin
      read(m1[i]);
      inc(m1[i]);
   end;


   sort(1,inf+1);


end.

POJ 1700(过河问题)

玩过《雷顿》就知道这题可以贪心

小等于2人:1,2->

3人时:

1,3->

1<-

1,2->

1<-

否则:

1,2->

2<-

max1,max2->

1<-

OR

1,max1->

1<-

2,max2->

2<-

于是数据规模-2

Program P1700;
var
   t,n,i,j:longint;
   l,r:longint;
   a:array[1..1000] of longint;
procedure qsort(l,r:longint);
var
   i,j,m,p:longint;
begin
   i:=l;
   j:=r;
   m:=a[(l+r) shr 1];
   repeat
      while (a[i]<m) do inc(i);
      while (a[j]>m) do dec(j);
      if i<=j then
      begin
         p:=a[i];a[i]:=a[j];a[j]:=p;
         inc(i);
         dec(j);
      end;
   until i>j;
   if l<j then qsort(l,j);
   if i<r then qsort(i,r);

end;
function max(a,b:longint):longint;
begin
   if a<b then exit(b) else exit(a);
end;
function min(a,b:longint):longint;
begin
   if a>b then exit(b) else exit(a);
end;

function ww(x:longint):longint;
var
   i,j:longint;
begin
   if x=1 then exit(a[1]);
   if x=2 then exit(a[2]);
   if x=3 then exit(a[1]+a[2]+a[3]);
   i:=2*a[1]+a[x]+a[x-1];
   j:=2*a[2]+a[1]+a[x];
   exit(ww(x-2)+min(i,j));
                           //1,2-> 1< r1,r2-> 2<=
end;
begin
   read(t);
   while (t>0) do
   begin
      read(n);
      for i:=1 to n do read(a[i]);
      qsort(1,n);
      l:=1;r:=n;

      writeln(ww(n));

      dec(t);
   end;
end.

CF 187A(从后取数的重排数列)

题目大意:一串数,每次把最后那个数挪到前面任意位置,就最少挪动次数

显然一个数最多挪一次(只能从后取的话,插2次的一定能变成1次)

因此找最后挪动的数即可,最后挪动的数即由于与下序列的连线与之前的交叉,其它数无论怎么挪都无法影响到它)

Program DD;
const
   maxn=200000;
var
   n,i,j,l,r:longint;
   a,b,hposa,hposb:array[1..maxn] of longint;
begin
   read(n);
   for i:=1 to n do
   begin
      read(a[i]);
      hposa[a[i]]:=i;
   end;
   for i:=1 to n do
   begin
      read(b[i]);
      hposb[b[i]]:=i;
   end;
   r:=0;
   for i:=1 to n do
   begin
       if r<hposb[a[i]] then r:=hposb[a[i]]
       else break;
   end;
   if (r=hposb[a[i]]) then writeln('0') else
   writeln(n-i+1);

end.

POJ 1818(贪心)

让每个人每局都与可战胜的人中最强的打,看有无可行解……

Program p1818;
var
   n,x,k,i,j,mid:longint;
   q:array[1..5100] of longint;
   f:array[1..5100] of longint;
function max(a,b:longint):longint;
begin
   if a<b then exit(b) else exit(a);
end;
function min(a,b:longint):longint;
begin
   if a<b then exit(a) else exit(b);
end;
function is_ac(person:longint):boolean;
var
   i,j,l,h,t:longint;
   size:longint;
begin
   fillchar(f,sizeof(f),0);
   fillchar(q,sizeof(q),0);
   q[1]:=person;
   size:=1;
   f[person]:=1;
   h:=1;t:=1;
   for l:=2 to x+1 do
   begin
      for i:=h to t do
      begin
         for j:=max(1,q[i]-k) to n do
         begin
            if f[j]=0 then
            begin
               inc(size);
               q[size]:=j;
               f[j]:=l;
               break;
            end;
         end;
      end;

      t:=size;

   end;

   if (size<n) then exit(false)
   else exit(true);


end;
begin
   read(n,k);
   x:=0;
   i:=1;
   while (i<n) do
   begin
      inc(x);
      i:=i shl 1;
   end;

   i:=1;j:=n;
   if is_ac(j) then i:=j;
   while (j-i>1) do
   begin
      mid:=(i+j) shr 1;
      if is_ac(mid) then i:=mid else j:=mid;
   end;
   writeln(i);
end.

POJ 1328(贪心)

贪心,区间排序

如果区间包含 略过,否则答案+1;

Program P1328;
var
   n,d,i,j,k,ans:longint;
   x:double;
   tag:boolean;
   map:array[1..1000,1..2] of double;
procedure qsort(l,r:longint);
var
   i,j:longint;
   m,p:double;
begin
   i:=l;
   j:=r;
   m:=map[(l+r) div 2,1];
   repeat
      while map[i,1]<m do inc(i);
      while map[j,1]>m do dec(j);
      if i<=j then
      begin
         p:=map[i,1];
         map[i,1]:=map[j,1];
         map[j,1]:=p;
         p:=map[i,2];
         map[i,2]:=map[j,2];
         map[j,2]:=p;
         inc(i);
         dec(j);
      end;
   until i>j;
   if l<j then qsort(l,j);
   if i<r then qsort(i,r);
end;
begin
   i:=1;
{   assign(input,'P1328.in');
   assign(output,'P1328.out');
   reset(input);
   rewrite(output);   }
   while not seekeof do
   begin
      tag:=true;
      read(n,d);
      if d<=0 then tag:=false;
      if (n=0) and (d=0) then break;
      j:=1;
      for k:=1 to n do
      begin
         read(map[j,1],map[j,2]);
         if map[j,2]<0  then continue;
         if d<map[j,2] then continue;
         x:=sqrt(d*d-map[j,2]*map[j,2]);
         map[j,2]:=map[j,1]+x;
         map[j,1]:=map[j,1]-x;
         inc(j);
      end;
      dec(j);
      if tag and (j=n) then
      begin
         qsort(1,j);
         ans:=1;
         x:=map[1,2];
         for k:=2 to j do
         begin
            if (map[k,2]<x) then
            begin
               x:=map[k,2];
            end
            else if (x<map[k,1]) then
            begin
               inc(ans);
               x:=map[k,2];
            end;

         end;

         writeln('Case ',i,': ',ans);
      end
      else writeln('Case ',i,': -1');
      inc(i);
   end;
 {  close(input);
   close(output);   }
end.