话说这题非常恶心,我整整写了上午4节自习+三节晚自习
题目大意:
  给你一些线段,让你选出最多的不相交的线段,并且让这些线段的字典序最小。
题解:
  首先,如果是不要求字典序的话,应该很简单吧,按线段的结束时间从大到小排序, 然后贪心地求解。
  好,这个思想很重要,我们先用这个方法来求出最多的线段数num,然后按字典序一个一个往里放,如果这条线段放进去不与已经放进去的线段重叠并且能够构成最优解,那么就把它放进去,这个题的思想就是这样的。
  那么如果要知道它是不是与原来放进去的线段重叠很简单,只要用一棵平衡树或者线段树就可以了,我写的平衡树,那么如何判断它是否能构成最优解呢?这就是这道题的关键。
  先定义闭区间[l,r]内最多放的线段数量为find(l,r)
  每次判断一条线段能否能构成最优解时,先找到这条线段往左往右能到达的最大距离,记为l,r,然后,插入这条线段后,这段区间的最多放的线段数量=find(l,a[x]-1)+find(b[x]+1,r)+1。这个很显然吧,然后就是find的求法了。
  我们先把所有的线段按右端点升序排序,然后把所有包含小线段的大线段都删去,你会发现,连左端点也变成了升序的。这有什么好处呢,就是你以后再用这些线段搜的时候就是最优的了。
  定义f[i,j]表示从第i条线段开始取2^j条不相交的线段能达到的最近的端点。这个是不是跟解决rmq问题的st表很相似?对,就是用的st表的思想。同样,这个东西能够在nlogn的时间内解决。先预处理一个get[i]表示i这个点右边的第一条线段。
  然后f[i,j]=f[get[d[f[i,j-1]]+1],j-1],这样就能在nlogn内预处理出f数组了。
  这次find就应该知道怎样求了吧?枚举一个左端点i,不断减小j,看是否达到右端点,达到了就加到find上面,然后将i移动到f[i,j]后边,直到j=0为止。
  额,最后输出很简单。
  sui哥用的线段树但貌似没我快。。sbt果然神奇。
附程序,250+行:
 program convention;
program convention;
 var ctree:array[0..200000] of record
 var ctree:array[0..200000] of record
 size,l,r,a,b:longint;
                          size,l,r,a,b:longint;
 end;
                          end;
 a,b,c,d,id,pos:array[0..200000] of longint;
     a,b,c,d,id,pos:array[0..200000] of longint;
 nb,get:array[0..400000] of longint;
     nb,get:array[0..400000] of longint;
 f:array[0..200000,0..30] of longint;
     f:array[0..200000,0..30] of longint;
 v:array[0..200000] of boolean;
     v:array[0..200000] of boolean;
 n,len,l,num,root,tot,fin:longint;
     n,len,l,num,root,tot,fin:longint;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure qsort(x,y:longint);
 procedure qsort(x,y:longint);
 var g,t,s,l,r:longint;
  var g,t,s,l,r:longint;
 begin
  begin
 t:=b[(x+y) div 2];l:=x;
   t:=b[(x+y) div 2];l:=x;
 s:=a[(x+y) div 2];r:=y;
   s:=a[(x+y) div 2];r:=y;
 repeat
   repeat
 while (b[l]<t) or ((b[l]=t) and (a[l]>s)) do inc(l);
     while (b[l]<t) or ((b[l]=t) and (a[l]>s)) do inc(l);
 while (b[r]>t) or ((b[r]=t) and (a[r]<s)) do dec(r);
     while (b[r]>t) or ((b[r]=t) and (a[r]<s)) do dec(r);
 if l<=r then begin
     if l<=r then begin
 g:=a[l];a[l]:=a[r];a[r]:=g;
     g:=a[l];a[l]:=a[r];a[r]:=g;
 g:=b[l];b[l]:=b[r];b[r]:=g;
     g:=b[l];b[l]:=b[r];b[r]:=g;
 g:=id[l];id[l]:=id[r];id[r]:=g;
     g:=id[l];id[l]:=id[r];id[r]:=g;
 pos[id[l]]:=l;pos[id[r]]:=r;
     pos[id[l]]:=l;pos[id[r]]:=r;
 inc(l);dec(r);
     inc(l);dec(r);
 end;
     end;
 until l>r;
    until l>r;
 if l<y then qsort(l,y);
   if l<y then qsort(l,y);
 if x<r then qsort(x,r);
   if x<r then qsort(x,r);
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure qusort(x,y:longint);
 procedure qusort(x,y:longint);
 var g,t,l,r:longint;
  var g,t,l,r:longint;
 begin
  begin
 t:=nb[(x+y) div 2];
   t:=nb[(x+y) div 2];
 l:=x;r:=y;
   l:=x;r:=y;
 repeat
   repeat
 while nb[l]<t do inc(l);
     while nb[l]<t do inc(l);
 while nb[r]>t do dec(r);
     while nb[r]>t do dec(r);
 if l<=r then begin
     if l<=r then begin
 g:=nb[l];nb[l]:=nb[r];nb[r]:=g;
     g:=nb[l];nb[l]:=nb[r];nb[r]:=g;
 inc(l);dec(r);
     inc(l);dec(r);
 end;
     end;
 until l>r;
    until l>r;
 if l<y then qusort(l,y);
   if l<y then qusort(l,y);
 if x<r then qusort(x,r);
   if x<r then qusort(x,r);
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure change(var x:longint);
 procedure change(var x:longint);
 var l,r,mid:longint;
  var l,r,mid:longint;
 begin
  begin
 l:=1;r:=len;
   l:=1;r:=len;
 repeat
    repeat
 mid:=(l+r) div 2;
     mid:=(l+r) div 2;
 if x>nb[mid] then l:=mid+1
     if x>nb[mid] then l:=mid+1
 else r:=mid-1;
              else r:=mid-1;
 until l>r;
     until l>r;
 x:=l;
    x:=l;
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure tl(var u:longint);
 procedure tl(var u:longint);
 var t:longint;
  var t:longint;
 begin
  begin
 t:=ctree[u].r;
   t:=ctree[u].r;
 ctree[u].r:=ctree[t].l;
   ctree[u].r:=ctree[t].l;
 ctree[t].l:=u;
   ctree[t].l:=u;
 ctree[t].size:=ctree[u].size;
   ctree[t].size:=ctree[u].size;
 ctree[u].size:=ctree[ctree[u].l].size+ctree[ctree[u].r].size+1;
   ctree[u].size:=ctree[ctree[u].l].size+ctree[ctree[u].r].size+1;
 u:=t;
   u:=t;
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure tr(var u:longint);
 procedure tr(var u:longint);
 var t:longint;
  var t:longint;
 begin
  begin
 t:=ctree[u].l;
   t:=ctree[u].l;
 ctree[u].l:=ctree[t].r;
   ctree[u].l:=ctree[t].r;
 ctree[t].r:=u;
   ctree[t].r:=u;
 ctree[t].size:=ctree[u].size;
   ctree[t].size:=ctree[u].size;
 ctree[u].size:=ctree[ctree[u].l].size+ctree[ctree[u].r].size+1;
   ctree[u].size:=ctree[ctree[u].l].size+ctree[ctree[u].r].size+1;
 u:=t;
   u:=t;
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure maintain(var u:longint;flag:boolean);
 procedure maintain(var u:longint;flag:boolean);
 begin
  begin
 if not flag then
   if not flag then
 if ctree[ctree[ctree[u].l].l].size>ctree[ctree[u].r].size
    if ctree[ctree[ctree[u].l].l].size>ctree[ctree[u].r].size 
 then tr(u)
     then tr(u)
 else
     else 
 if ctree[ctree[ctree[u].l].r].size>ctree[ctree[u].r].size
    if ctree[ctree[ctree[u].l].r].size>ctree[ctree[u].r].size 
 then begin tl(ctree[u].l);tr(u); end
     then begin tl(ctree[u].l);tr(u); end
 else exit
      else exit
 else
     else
 if ctree[ctree[ctree[u].r].r].size>ctree[ctree[u].l].size
    if ctree[ctree[ctree[u].r].r].size>ctree[ctree[u].l].size 
 then tl(u)
     then tl(u)
 else
     else
 if ctree[ctree[ctree[u].r].l].size>ctree[ctree[u].l].size
    if ctree[ctree[ctree[u].r].l].size>ctree[ctree[u].l].size
 then begin tr(ctree[u].r);tl(u); end
     then begin tr(ctree[u].r);tl(u); end
 else exit;
     else exit;
 maintain(ctree[u].l,false);
    maintain(ctree[u].l,false);
 maintain(ctree[u].r,true);
    maintain(ctree[u].r,true);
 maintain(u,true);
    maintain(u,true);
 maintain(u,false);
    maintain(u,false);
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure makeget;
 procedure makeget;
 var i:longint;
  var i:longint;
 begin
  begin
 for i:=1 to l do
   for i:=1 to l do
 get[c[i]]:=i;
    get[c[i]]:=i;
 for i:=c[l] downto 1 do
   for i:=c[l] downto 1 do
 if get[i]=0 then get[i]:=get[i+1];
    if get[i]=0 then get[i]:=get[i+1];
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 function find(x,y:longint):longint;
 function find(x,y:longint):longint;
 var i,j:longint;
  var i,j:longint;
 begin
  begin
 if x>=y then exit(0);
   if x>=y then exit(0);
 find:=0;
   find:=0;
 i:=get[x];
   i:=get[x];
 j:=fin;
   j:=fin;
 while j>=0 do begin
   while j>=0 do begin 
 while ((f[i,j]=0) or (d[f[i,j]]>y)) and (j>=0) do dec(j);
    while ((f[i,j]=0) or (d[f[i,j]]>y)) and (j>=0) do dec(j);
 if j>=0 then
    if j>=0 then
 inc(find,1 shl j);
    inc(find,1 shl j);
 i:=f[f[i,j],1];
    i:=f[f[i,j],1];
 end;
    end;
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 function cmp(x,st,ed:longint):boolean;
 function cmp(x,st,ed:longint):boolean;
 begin
  begin
 if find(st,a[x]-1)+find(b[x]+1,ed)+1=find(st,ed)
   if find(st,a[x]-1)+find(b[x]+1,ed)+1=find(st,ed)
 then exit(true)
    then exit(true)
 else exit(false);
    else exit(false);
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 function check(x,st,ed,u:longint):boolean;
 function check(x,st,ed,u:longint):boolean;
 begin
  begin
 if u=0 then
   if u=0 then 
 begin
    begin 
 if cmp(x,st,ed) then exit(true)
     if cmp(x,st,ed) then exit(true) 
 else exit(false);
                          else exit(false);
 end;
    end;
 if a[x]>ctree[u].b then
   if a[x]>ctree[u].b then 
 begin
    begin
 check:=check(x,ctree[u].b+1,ed,ctree[u].r);
     check:=check(x,ctree[u].b+1,ed,ctree[u].r);
 exit;
     exit;
 end else
    end else 
 if b[x]<ctree[u].a then
   if b[x]<ctree[u].a then
 begin
    begin
 check:=check(x,st,ctree[u].a-1,ctree[u].l);
     check:=check(x,st,ctree[u].a-1,ctree[u].l);
 exit;
     exit;
 end else exit(false);
    end else exit(false);
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure insert(x:longint; var u:longint);
 procedure insert(x:longint; var u:longint);
 begin
  begin
 if u=0 then
   if u=0 then 
 begin
    begin
 inc(tot);
     inc(tot);
 ctree[tot].size:=1;
     ctree[tot].size:=1;
 ctree[tot].a:=a[x];
     ctree[tot].a:=a[x];
 ctree[tot].b:=b[x];
     ctree[tot].b:=b[x];
 u:=tot;
     u:=tot;
 exit;
     exit;
 end;
    end;
 if a[x]>ctree[u].a then
   if a[x]>ctree[u].a then
 begin
    begin
 insert(x,ctree[u].r);
     insert(x,ctree[u].r);
 inc(ctree[u].size);
     inc(ctree[u].size);
 maintain(u,true);
     maintain(u,true);
 end else
    end else
 begin
    begin
 insert(x,ctree[u].l);
     insert(x,ctree[u].l);
 inc(ctree[u].size);
     inc(ctree[u].size);
 maintain(u,false);
     maintain(u,false);
 end;
     end;
 end;
  end;    
 {-----------------------------------------}
 {-----------------------------------------}
 procedure init;
 procedure init;
 var i:longint;
  var i:longint;
 begin
  begin
 readln(n);
   readln(n);
 for i:=1 to n do begin
   for i:=1 to n do begin
 readln(a[i],b[i]);
    readln(a[i],b[i]);
 pos[i]:=i;id[i]:=i;
    pos[i]:=i;id[i]:=i;
 inc(len);nb[len]:=a[i];
    inc(len);nb[len]:=a[i];
 inc(len);nb[len]:=b[i];
    inc(len);nb[len]:=b[i];
 end;
    end;
 qusort(1,len);
    qusort(1,len);
 len:=1;
    len:=1;
 for i:=1 to n*2 do
    for i:=1 to n*2 do
 if nb[len]<>nb[i] then
    if nb[len]<>nb[i] then
 begin
     begin
 inc(len);nb[len]:=nb[i];
      inc(len);nb[len]:=nb[i];
 end;
     end;
 for i:=1 to n do
    for i:=1 to n do
 begin
     begin
 change(a[i]);change(b[i]);
      change(a[i]);change(b[i]);
 end;
     end;
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure makef;
 procedure makef;
 var i,j:longint;
  var i,j:longint;
 begin
  begin
 for i:=1 to l do f[i,0]:=i;
   for i:=1 to l do f[i,0]:=i;
 for i:=1 to l do
   for i:=1 to l do
 f[i,1]:=f[get[d[f[i,0]]+1],0];
    f[i,1]:=f[get[d[f[i,0]]+1],0];
 for j:=2 to fin do
   for j:=2 to fin do
 for i:=1 to l-1 shl j+1 do
    for i:=1 to l-1 shl j+1 do
 f[i,j]:=f[f[f[i,j-1],1],j-1];
      f[i,j]:=f[f[f[i,j-1],1],j-1];
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure prepare;
 procedure prepare;
 var i,tmp:longint;
  var i,tmp:longint;
 begin
  begin
 root:=0;
    root:=0;
 qsort(1,n);
   qsort(1,n);
 c[1]:=a[1];d[1]:=b[1];
   c[1]:=a[1];d[1]:=b[1];
 l:=1;i:=1;
   l:=1;i:=1;
 for i:=1 to n do
  for i:=1 to n do
 if (a[i]>c[l]) and (b[i]>d[l]) then
    if (a[i]>c[l]) and (b[i]>d[l]) then
 begin
    begin 
 inc(l);c[l]:=a[i];d[l]:=b[i];
     inc(l);c[l]:=a[i];d[l]:=b[i];
 end;
    end;
 fin:=trunc(ln(l)/ln(2));
    fin:=trunc(ln(l)/ln(2));
 makeget;
     makeget;
 makef;
     makef;
 tmp:=0;num:=0;
    tmp:=0;num:=0;
 for i:=1 to l do
   for i:=1 to l do
 if c[i]>tmp then
     if c[i]>tmp then 
 begin inc(num);tmp:=d[i];
      begin inc(num);tmp:=d[i];
 end;
      end;
 end;
  end;
 {-----------------------------------------}
 {-----------------------------------------}
 procedure main;
 procedure main;
 var i:longint;
  var i:longint;
 begin
  begin
 prepare;
  prepare;
 for i:=1 to n do
  for i:=1 to n do 
 if check(pos[i],1,len,root) then
    if check(pos[i],1,len,root) then 
 begin
     begin 
 v[i]:=true;
      v[i]:=true;
 insert(pos[i],root);
      insert(pos[i],root);
 end;
     end;
 writeln(num);
   writeln(num);
 for i:=1 to n do
  for i:=1 to n do
 if v[i] then write(i,' ');writeln;
   if v[i] then write(i,' ');writeln;
 end;
 end;
 {-----------------------------------------}
 {-----------------------------------------}
 begin
 begin
 assign(input,'convention.in');reset(input);
  assign(input,'convention.in');reset(input);
 assign(output,'convention.out');rewrite(output);
  assign(output,'convention.out');rewrite(output);
 init;
  init;
 main;
  main;
 close(output);
  close(output);
 end.
 end.过两天要参加apio了,所以把近三年的apio都写完了,这道题是最恶心的一道。
如果有更好的做法欢迎指教。 
	
posted on 2010-04-26 21:17 
一芥书生 阅读(1015) 
评论(2)  编辑 收藏 引用