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 2588(解析几何+并查集)

题目就是早从左到右的路

注意输入的实数

这题图画好就行,别像我一开始把图弄反就成

从上开始找,若找到一个与下边界相邻的就无解,找到与左边相邻的记圆与左边界相交的下边的点(相当于左上角挖去一块),右边同理。

Program snake;
const
   maxn=1000;
var
   n,i,j:longint;
   x,y,r,lc,rc:array[1..maxn] of double;
   maxl,maxr:double;
   father:array[1..maxn] of longint;
   b,up,down,left,right:array[1..maxn] of boolean;
function getfather(x:longint):longint;
begin
   if father[x]=x then exit(x);
   father[x]:=getfather(father[x]);
   exit(father[x]);
end;
Procedure union(x,y:longint);
begin
   father[father[x]]:=father[father[y]];
end;
function distance(i,j:longint):double;
begin
   exit(sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j])));
end;
function dis(x1,y1,x2,y2:double):double;
begin
   exit(sqrt(sqr(x1-x2)+sqr(y1-y2)));
end;

begin
   fillchar(b,sizeof(b),false);
   fillchar(up,sizeof(up),false);
   fillchar(down,sizeof(down),false);
   fillchar(left,sizeof(left),false);
   fillchar(right,sizeof(right),false);
   fillchar(lc,sizeof(lc),0);
   fillchar(rc,sizeof(rc),0);
   maxl:=1000;maxr:=1000;

   read(n);
   for i:=1 to n do
   begin
      read(x[i],y[i],r[i]);
      father[i]:=i;
      for j:=1 to i-1 do
         if distance(i,j)<r[i]+r[j] then
            if getfather(i)<>getfather(j) then
               union(i,j);
      if (y[i]<r[i]) then down[i]:=true;
      if (y[i]+r[i]>1000) then up[i]:=true;
      if (x[i]<r[i]) then
      begin
         left[i]:=true;
         lc[i]:=y[i]-sqrt(sqr(r[i])-sqr(x[i]));
      end;
      if (x[i]+r[i]>1000) then
      begin
         right[i]:=true;
         rc[i]:=y[i]-sqrt(sqr(r[i])-sqr(1000-x[i]));
      end;

   end;
   for i:=1 to n do
      if (up[i]) and not(b[i]) then
      begin
         for j:=1 to n do
            if father[i]=father[j] then
            begin
               b[j]:=true;
               if (down[j]) then
               begin
                  writeln('Bill will be bitten.');
                  halt;
               end;
               if left[j] then
               begin
                  if lc[j]<maxl then maxl:=lc[j];

               end;
               if right[j] then
               begin
                  if rc[j]<maxr then maxr:=rc[j];
               end;


            end;
      end;
   writeln('Bill enters at (0.00, ',maxl:2:2,') and leaves at (1000.00, ',maxr:2:2,').');




end.

POJ 3122(二分答案)

二分答案……

Program pie;
const
   lef=0.00001;
var
   t,n,f,i,j:longint;
   r:array[1..10000] of longint;
   s:array[1..10000] of double;
   maxs:double;
procedure sort(l,r:double);
var
   m:real;
   i,j,tot:longint;
begin
   m:=(l+r)/2;
   tot:=0;
   for i:=1 to n do inc(tot,trunc(s[i]/m));

   if tot>=f then
   begin
      if r-l<lef then writeln(r:4:4)
      else sort(m,r);


   end
   else sort(l,m);










end;
begin
   read(t);
   while (t>0) do
   begin
      read(n,f);
      inc(f);
      for i:=1 to n do
      begin
         read(r[i]);
         s[i]:=sqr(r[i])*pi;
      end;
      maxs:=s[1];
      for i:=2 to n do
         if maxs<s[i] then maxs:=s[i];
      sort(0,maxs);

      dec(t);
   end;
end.

POJ 3844(同余)

果断同余……

D[j]-D[i]  mod  k =0

D[j]=D[i]

求有多少相等数对,用队列O(n)

Program P3844;
const
   maxn=50000;
   maxd=1000000;
var
   ans,t,f,n,i,j:longint;
   d:array[0..maxn] of longint;
procedure qsort(l,r:longint);
var
   i,j,m,p:longint;
begin
   i:=l;j:=r;
   m:=d[(l+r) shr 1];
   repeat
      while d[i]<m do inc(i);
      while d[j]>m do dec(j);
      if i<=j then
      begin
         p:=d[i];
         d[i]:=d[j];
         d[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(t);
   d[0]:=0;
   while (t>0) do
   begin
      read(f,n);
      for i:=1 to n do
      begin
         read(d[i]);
         d[i]:=(d[i]+d[i-1]) mod f;
      end;
      qsort(1,n);

      ans:=0;
      i:=0;j:=0;
      while (i<=n) do
      begin
         while (d[i]=d[j]) and (j<n) do inc(j);
         if d[i]<>d[j] then dec(j);
         inc(ans,((j-i+1)*(j-i)) shr 1);
         i:=j+1;
         inc(j);
      end;


      writeln(ans);

      dec(t);
   end;
end.

POJ 2184(01背包+滚动数组)

01背包 模板题

Program dd;
const
   maxn=1000;
   maxv=100000;
   minv=-100000;
   NULL=-2139062144;
var
   n,i,j,ans,p,np:longint;
   ts,tf:array[1..maxn] of longint;
   f:array[0..1,minv..maxv] of longint;
function max(a,b:longint):longint;
begin
   if a<b then exit(b) else exit(a);
end;
begin
   read(n);
   for i:=1 to n do read(ts[i],tf[i]);
   fillchar(f,sizeof(f),128);
   f[0,0]:=0;
   for i:=1 to n do
   begin
      p:=i mod 2;
      fillchar(f[p],sizeof(f[p]),128);
      np:=(p+1) mod 2;

      for j:=maxv downto minv do
      begin
         f[p,j]:=f[np,j];
         if (minv<=j-ts[i]) and (j-ts[i]<=maxv) then
            if (f[np,j-ts[i]]<>NULL) then
               f[p,j]:=max(f[p,j],f[np,j-ts[i]]+tf[i]);



      end;
   end;


   ans:=0;
   for i:=0 to maxv do
      if (f[n mod 2,i]>=0) and (ans<f[n mod 2,i]+i) then ans:=f[n mod 2,i]+i;

   writeln(ans);

end.

POJ 2110(最小生成树)

这题的思路就是找一个范围,看看这个范围是否可行

主流是二分Ans,我是先把点排序,求最小生成树检查首位的

Program P2110;
type
   ed=record
      u,v,w:longint;
      end;
var
   a:array[1..120,1..120] of longint;
   edge:array[0..30000] of ed;
   n,i,j,size,ans:longint;
   now:longint;
   father:array[0..10001] of longint;
   b:array[0..121,0..121] of boolean;
procedure add(u,v,w:longint);
begin
   inc(size);
   edge[size].u:=u;
   edge[size].v:=v;
   edge[size].w:=w;

end;
procedure qsort(l,r:longint);
var
   i,j,m:longint;
   p:ed;
begin
   i:=l;
   j:=r;
   m:=edge[(l+r) shr 1].w;
   repeat
      while edge[i].w<m do inc(i);
      while edge[j].w>m do dec(j);
      if i<=j then
      begin
         p:=edge[i];
         edge[i]:=edge[j];
         edge[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 getfather(x:longint):longint;
begin
   if x=father[x] then exit(x);
   father[x]:=getfather(father[x]);
   exit(father[x]);
end;
function hash(x,y:longint):longint;
begin
  exit((x-1)*n+y);
end;
begin
   size:=0;
   read(n);
   for i:=1 to n do
      for j:=1 to n do
      begin
         read(a[i,j]);
         add(i,j,a[i,j]);
      end;

  // (0,n*n)
   qsort(1,size);


   edge[0].w:=edge[1].w-1;
   ans:=110;
   //                 writeln;
   for i:=1 to size do
   begin

      if edge[i].w=edge[i-1].w then continue;
      for j:=0 to n*n do father[j]:=j;
      fillchar(b,sizeof(b),false);
      for j:=i to size do
      begin
         b[edge[j].u,edge[j].v]:=true;
         now:=hash(edge[j].u,edge[j].v);

         if b[edge[j].u-1,edge[j].v] then
            if getfather(now)<>getfather(now-n) then
            begin
               father[father[now]]:=father[father[now-n]];
               if getfather(0)=getfather(n*n) then break;
            end;

         if b[edge[j].u+1,edge[j].v] then
            if getfather(now)<>getfather(now+n) then
            begin
               father[father[now]]:=father[father[now+n]];
               if getfather(0)=getfather(n*n) then break;
            end;

         if b[edge[j].u,edge[j].v+1] then
            if getfather(now)<>getfather(now+1) then
            begin
               father[father[now]]:=father[father[now+1]];
               if getfather(0)=getfather(n*n) then break;
            end;

         if b[edge[j].u,edge[j].v-1] then
            if getfather(now)<>getfather(now-1) then
            begin
               father[father[now]]:=father[father[now-1]];
               if getfather(0)=getfather(n*n) then break;
            end;



         if getfather(1)=getfather(n*n) then break;

      end;



      if getfather(1)<>getfather(n*n) then break;
      if ans>edge[j].w-edge[i].w then ans:=edge[j].w-edge[i].w;


   end;
   writeln(ans);



end.

POJ 1952(最长不下降子序列的个数)

求一个序列的最长不下降子序列的长度,与个数(相同数列算1个)

关键是如何判重。

显然如果之前有一个尾数相同且长度相同的序列,哪么后一个包含前一个所有可能的序列相同的序列,故将前一个序列删除(重复)

Program P1952;
var
   n,i,j,ans:longint;
   a,len,f,path:array[1..5000] of longint;
begin
   read(n);
   for i:=1 to n do read(a[i]);
   for i:=1 to n do
   begin
      len[i]:=1;
      f[i]:=1;
      path[i]:=i;
      for j:=i-1 downto 1 do
         if (a[j]>a[i]) and (len[j]+1>len[i]) then
         begin
            len[i]:=len[j]+1;
            f[i]:=f[j];
         end
         else if (a[j]>a[i]) and (len[j]+1=len[i]) then inc(f[i],f[j]);


      for j:=1 to i-1 do
         if (a[i]=a[j]) and (len[i]=len[j]) then f[j]:=0;



   end;
   j:=0;
   for i:=1 to n do if len[i]>j then j:=len[i];
   ans:=0;
   for i:=1 to n do if len[i]=j then inc(ans,f[i]);

   writeln(j,' ',ans);


end.

POJ 1951(空串特判)

这题的教训是 要特判空串

Program P1951;
var
   s:string;
   len,i,j:longint;
   b:array[0..10000] of boolean;
function isdight(x:longint):boolean;
begin
   if (x>=65) and (x<=90) then exit(false);
   if (x>=97) and (x<=122) then exit(false);
   exit(true);

end;
begin
   readln(s);
   fillchar(b,sizeof(b),false);
   b[ord('a')]:=true;
   b[ord('e')]:=true;
   b[ord('i')]:=true;
   b[ord('o')]:=true;
   b[ord('u')]:=true;
   b[ord('A')]:=true;
   b[ord('E')]:=true;
   b[ord('I')]:=true;
   b[ord('O')]:=true;
   b[ord('U')]:=true;

   i:=1;
   while i<=length(s) do
   begin
      if b[ord(s[i])] and not(isdight(ord(s[i]))) then delete(s,i,1)
      else
      begin
         b[ord(s[i])]:=true;
         inc(i);

      end;
   end;


   while (s[1]=' ') and (length(s)>=1) do delete(s,1,1);
   while (s[length(s)]=' ') and (length(s)>=1) do delete(s,length(s),1);
   i:=pos('  ',s);
   while i<>0 do
   begin
      delete(s,i,1);
      i:=pos('  ',s);
   end;
   i:=pos(' .',s);
   while i<>0 do
   begin
      delete(s,i,1);
      i:=pos(' .',s);
   end;
   i:=pos(' ,',s);
   while i<>0 do
   begin
      delete(s,i,1);
      i:=pos(' ,',s);
   end;
   i:=pos(' ?',s);
   while i<>0 do
   begin
      delete(s,i,1);
      i:=pos(' ?',s);
   end;



   writeln(s);

end.

POJ 1950(不打表做法)

这题就是搜……

注意设定maxn 要不然肯定爆 maxn=1*10^最大位数/2 1234..89-11121314这样的

Program aa;
const
   maxn=1000000000000000;
var
   n,t:longint;
   a:array[1..15] of char;
procedure dfs(l,sum,res,bl:int64);
var
   i,j:longint;
begin
   if l=n then
   begin
      res:=res+bl*sum;
      if res=0 then
      begin
         inc(t);
         if t<=20 then
         begin
            for i:=1 to n-1 do write(i,' ',a[i],' ');
            writeln(n);


         end;
      end;


      exit;
   end;

   a[l]:='+';
   dfs(l+1,l+1,res+bl*sum,1);
   a[l]:='-';
   dfs(l+1,l+1,res+bl*sum,-1);
   a[l]:='.';
   if sum<=maxn then
   if l+1<=9 then
      dfs(l+1,sum*10+(l+1),res,bl)
   else
      dfs(l+1,sum*100+(l+1),res,bl);


end;
begin
 {  assign(output,'a.pas');
   rewrite(output);
  }
   read(n);
   t:=0;
   dfs(1,1,0,1);
   writeln(t);

 //  close(output);
end.

POJ 3278(BFS-搜索范围)

这题是BFS水的

主要是范围

0<=n,k<=100000  但是有可能搜到200000……

半天功夫才A.

program P3278;
const
   maxn=200000;
var
   n,k,i,j:longint;
   q,deep:array[1..maxn] of longint;
   b:array[0..maxn] of boolean;
procedure add(x:longint);
begin
   if not(b[x]) then
   begin
      b[x]:=true;
      inc(j);
      q[j]:=x;
      deep[j]:=deep[i]+1;
   end;
end;
begin
   read(n,k);
   i:=1;
   j:=1;
   fillchar(b,sizeof(b),false);
   b[n]:=true;
   q[1]:=n;deep[1]:=0;
   if n=k then
   begin
      writeln('0');
      halt;
   end;


   while i<=j do
   begin
      if (q[i]>0) then add(q[i]-1);
      if b[k] then break;
      if (q[i]<maxn) then add(q[i]+1);
      if b[k] then break;
      if (q[i]*2<maxn) then add(q[i]*2);
      if b[k] then break;
      inc(i);
   end;
   writeln(deep[j]);

end.