На форумі обговорюються лише питання, пов'язані з олімпіадою
Ви не зайшли.
Тесты: http://www.proveryalka.narod.ru/tests.html
Решения на Паскале: http://www.h0h0l.narod.ru
Временная сложность моих решений:
NewDomino - O(50K)
DSP2 - O(N^3)
Army - не решил
Lake - не решил
Message - O(Length(S1)*Length(S2)) - тупо, но лучше не придумал...
У кого решения лучше - пишите сюда.
Если придумали тесты - тоже пишите (все тесты, которые будут здесь написаны, я добавлю на свой сайт)
Поза форумом
NewDomino - O(K)
DSP - O(N^2) - точно не помню
Army - O(K*N^2)
Lake - O(V^2+V*log V)
Message - O(Length(S1)*Length(S2))
Если кто знает крутой метод решения Army или Message - расскажите, пожалуйста!!
Поза форумом
Батыев Андрей написав:
NewDomino - O(K)
DSP - O(N^2) - точно не помню
Army - O(K*N^2)
Lake - O(V^2+V*log V)
Круто!!!
можешь скинуть мне решения? mailto:h0h0l@yandex.ru
Поза форумом
2 Батыев Андрей:
Попробуй поискать такие алгоритмы:
алгоритм Рабина-Карпа
алгоритм Кнута-Морриса-Пратта
алгоритм Бойера-Мура
поиск подстрок с помощью конечных автоматов
Відредаговано Anna (2006-01-19 13:10:53)
Поза форумом
NewDomino - O(K)
DSP - O(N^3)
Army - O(K*N) - в лутшем случае, на самом галимом моём тесте - 4сек
Lake - O(V^3), за счёт оптимизаций в лутшем случае O(V^2)
Message - O(log(min(Length(S1),Length(S2)))*(Length(S1)+Length(S2))
Відредаговано xXx (2006-01-19 14:00:58)
Поза форумом
Батыев Андрей написав:
Если кто знает крутой метод решения Army или Message - расскажите, пожалуйста!!
Army
Читаем v<=(номер 1-ого солдата), запоминаем min:=v далее в строю ниже него (op:=v-1) солдат, значит выбрать K солдат можно C(N-op-1, K) способами (C(M,N) - количество способов выбрать из M по N элементов, C(M,N)=m!/(n!(m-n)!))
далее цикл
for I:=2 to N do begin
Read(v);
if v>min then begin
op:=op+(v-min)-1;
min:=v;
end else
op:=op-1;
C(N-I-op, K, cnt_i);
Count:=Count+cnt_i;
end;
функция C(M, N) оптимизирована под данную задачу;
памяти "кушает" прилично но тест 100000 2 1 2 3 4 ... k ... 100000 работает за 0,078 сек (по мнению Винды)
Вот мой код:
program Army;
//{$DEFINE test}
const
MaxCm = 100000;
type
TArrayOfCmn = array[0..MaxCm] of Int64;
var
C_val: TArrayOfCmn;
Cu : array[0..MaxCm] of Boolean;
procedure Int2String(a: Int64; var S: string);
function Str100(i: Integer): string;
begin
Str100 := Chr(i div 10 + Ord('0')) + Chr(i mod 10 + Ord('0'));
end;
var
R: Integer;
Is_Neg: Boolean;
begin
S := '';
Is_Neg := a<0;
if Is_Neg then a:=-a;
repeat
R:=a mod 100;
a:=a div 100;
Insert(Str100(R), S, 1);
until (a=0) or (Length(S) = 254);
while (Length(S) > 1) and (S[1] = '0') do Delete(S, 1, 1);
if Is_Neg then Insert('-', S, 1);
end;
procedure C(const M, N: LongInt; var Res: Int64);
var
NC: Int64;
I: LongInt;
begin
if N>M then
Res:=0
else if Cu[M]{(C_val[M]<>nil)and(C_val[M]^[N]<>nil)} then
Res:=C_val[M]
else if N=1 then
Res:=M
else if N=0 then
Res:=0
else if N=M then
Res:=1
else begin
I:=M;
while (I>N)and(not Cu[i]) do
Dec(I);
if I=N then
NC:=1
else
NC:=C_val[i];
while I<M do begin
NC:=(NC*(I+1)) div (I+1-N);
Inc(I);
C_val[i]:=NC;
Cu[i]:=True;
end;
Res:=NC;
end;
Cu[M]:=True;
C_val[M]:=Res;
end;
procedure ReadData;
var
min, v, op, I, N, K: LongInt;
Count, cnt_i: Int64;
Res: String;
begin
Read(N, K);
if K=0 then begin
WriteLn(N);
Exit;
end;
FillChar(Cu, SizeOf(Cu), 0);
Read(v);
op:=v-1;
min:=v;
C(N-1-op, K, Count);
for I:=2 to N do begin
Read(v);
if v>min then begin
op:=op+(v-min)-1;
min:=v;
end else
op:=op-1;
C(N-I-op, K, cnt_i);
Count:=Count+cnt_i;
end;
Int2String(Count, Res);
Writeln(Res);
end;
begin
{$IFDEF test}
Assign(Input, 'Input.dat');
Assign(Output, 'Output.dat');
Reset(Input);
Rewrite(Output);
{$ENDIF}
ReadData;
{$IFDEF test}
Close(Output);
Close(Input);
{$ENDIF}
end.Поза форумом
Извините за не точности - только щас откопал код в компе.
DSP2 - таки O(N^3)
LAKE - просто O(V^2), где V - кол-во всех вершин
Значит так:
ARMY
{$A+,B-,D-,E+,F-,G+,I-,L-,N+,O-,P-,Q-,R-,S-,T-,V+,X+,Y-}
program army;
const maxn=100000;
maxk=11;
var aa:array[1..maxn]of longint;
n,k:longint;
res:array[1..maxn,1..maxk]of comp;
procedure Init;
var i:longint;
begin
read(n,k);
inc(k);
for i:=1 to n do
read(aa[i]);
end;
procedure Solve;
var i,j,l:longint;
begin
for i:=1 to n do
res[i,1]:=1;
for l:=2 to k do
for i:=1 to n do
begin
res[i,l]:=0;
for j:=1 to i-1 do
if aa[j]<aa[i] then
res[i,l]:=res[i,l]+res[j,l-1];
end;
end;
procedure WriteResult;
var t:comp;
i:longint;
begin
t:=0;
for i:=1 to n do
t:=t+res[i,k];
writeln(t:0:0);
end;
begin
Init;
Solve;
WriteResult;
end.DSP2
{$A+,B-,D-,E+,F-,G+,I-,L-,N+,O-,P-,Q-,R-,S-,T-,V+,X+,Y-}
program dsp2;
const maxn=52;
var c:array[1..maxn]of longint;
res,len,n:integer;
procedure Init;
var i:integer;
begin
read(len);
read(n);
c[1]:=0;
for i:=2 to n+1 do
read(c[i]);
n:=n+2;
c[n]:=len;
end;
procedure Solve;
var a:array[1..maxn,1..maxn]of longint;
i,j,l,k:integer;
begin
for i:=1 to n do
for j:=1 to n do
a[i,j]:=0;
for l:=2 to n-1 do
for i:=1 to n-l do
begin
j:=i+l; a[i,j]:=-1;
for k:=i+1 to j-1 do
if(a[i,j]=-1)or(a[i,j]>a[i,k]+a[k,j])then
a[i,j]:=a[i,k]+a[k,j];
a[i,j]:=a[i,j]+c[j]-c[i];
end;
res:=a[1,n];
end;
procedure WriteResult;
begin
write(res);
end;
begin
Init;
Solve;
WriteResult;
end.NEWDOMINO
{$A+,B-,D-,E+,F-,G+,I-,L-,N+,O-,P-,Q-,R-,S-,T-,V+,X+,Y-}
program newdomino;
type plist=^list;
list=record
d:longint;
next:plist;
end;
const maxn=50;
maxl=1000;
var g:array[1..maxn,1..maxn]of shortint;
num:array[1..maxn]of integer;
n:integer;
res:boolean;
cycle:plist;
procedure Init;
var i,j,a,b:integer;
begin
for i:=1 to maxn do
begin
num[i]:=0;
for j:=1 to maxn do
g[i,j]:=0;
end;
read(n);
for i:=1 to n do
begin
read(a,b);
inc(g[a,b]);
inc(g[b,a]);
inc(num[a]); inc(num[b]);
end;
end;
procedure ListAppend(d:longint;p:plist);
var t:plist;
begin
New(t);
t^.d:=d;
t^.next:=p^.next;
p^.next:=t;
end;
procedure BuildCycle;
var totalnum:longint;
i,j,first:integer;
p:plist;
us:array[1..maxn]of boolean;
begin
{prepare loop}
totalnum:=0;
for i:=1 to maxn do
begin
totalnum:=totalnum+num[i];
us[i]:=false;
end;
{making null plug}
new(cycle);
cycle^.next:=nil;
cycle^.d:=-111;
p:=cycle;
{first loop}
for i:=1 to maxn do
if (num[i]<>0) then
begin
first:=i;
break;
end;
repeat
totalnum:=totalnum-2;
ListAppend(i,p);
p:=p^.next;
for j:=1 to maxn do
if g[i,j]<>0 then
begin
dec(num[i]);
dec(num[j]);
dec(g[i,j]);
dec(g[j,i]);
i:=j;
break;
end;
us[i]:=true;
until i=first;
{main loop}
while(totalnum>0)do
begin
for i:=1 to maxn do
if (num[i]<>0)and us[i] then
begin
first:=i;
break;
end;
{search for position to insert}
p:=cycle;
while(p^.next^.d<>first)do
p:=p^.next;
{loop for appending}
repeat
totalnum:=totalnum-2;
ListAppend(i,p);
p:=p^.next;
for j:=1 to maxn do
if g[i,j]<>0 then
begin
dec(num[i]);
dec(num[j]);
dec(g[i,j]);
dec(g[j,i]);
i:=j;
break;
end;
us[i]:=true;
until i=first;
end;
{delete plug}
p:=cycle^.next;
Dispose(cycle);
cycle:=p;
end;
procedure Solve;
var p:boolean;
i,j:integer;
us:array[1..maxn]of boolean;
begin
res:=true;
for i:=1 to maxn do
begin
res:=res and (num[i] mod 2=0);
us[i]:=false;
end;
for i:=1 to n do
if num[i]<>0 then
break;
us[i]:=true;
repeat
p:=true;
for i:=1 to n do
for j:=1 to n do
if (us[i] xor us[j])and(g[i,j]<>0) then
begin
us[i]:=true;
us[j]:=true;
p:=false;
end;
until p;
for i:=1 to n do
res:=res and (us[i] or (num[i]=0));
if res then
begin
BuildCycle;
end;
end;
procedure WriteResult;
var i,first:integer;
p:plist;
begin
if res then
begin
first:=cycle^.d;
write(first,' ');
p:=cycle^.next;
dispose(cycle);
cycle:=p;
while cycle<>nil do
begin
write(cycle^.d,' ',cycle^.d,' ');
p:=cycle^.next;
dispose(cycle);
cycle:=p;
end;
writeln(first);
end
else
writeln(-1);
end;
begin
Init;
Solve;
WriteResult;
end.LAKE
{$A+,B-,D-,E+,F-,G+,I-,L-,N+,O-,P-,Q-,R-,S-,T-,V+,X+,Y-}
program lake;
const maxn=500;
maxl=10;
maxv=20;
type point=record
x,y:extended;
end;
polygon=record
n:integer;
v:array[1..maxv]of point;
end;
line=record
a,b,c:extended;
end;
var polygons:array[1..maxl]of polygon;
l,n:integer;
pstart,pend:point;
g:array[1..maxn,1..maxn]of extended;
d:array[1..maxn]of extended;
procedure Init;
var i,j:integer;
x,y,b:extended;
begin
read(pstart.x,pstart.y);
read(pend.x,pend.y);
read(l);
for i:=1 to l do
begin
read(polygons[i].n);
read(x,y);
read(polygons[i].v[1].x,polygons[i].v[1].y);
b:=2*pi/polygons[i].n;
for j:=2 to polygons[i].n do
begin
polygons[i].v[j].x:=(polygons[i].v[1].x-x)*cos(b*(j-1))+
(polygons[i].v[1].y-y)*sin(b*(j-1))+x;
polygons[i].v[j].y:=(polygons[i].v[1].y-y)*cos(b*(j-1))-
(polygons[i].v[1].x-x)*sin(b*(j-1))+y;
end;
end;
end;
procedure PointToLine(p1,p2:point;var r:line);
begin
r.a:=p1.y-p2.y;
r.b:=p2.x-p1.x;
r.c:=-p1.x*r.a-p1.y*r.b;
end;
function CheckIntersect(ap1,ap2,bp1,bp2:point):boolean;
var l1,l2:line;
w1,w2:extended;
res:boolean;
begin
PointToLine(ap1,ap2,l1);
PointToLine(bp1,bp2,l2);
w1:=l1.a*bp1.x+l1.b*bp1.y+l1.c;
w2:=l1.a*bp2.x+l1.b*bp2.y+l1.c;
res:=((w1>0)and(w2<0))or((w1<0)and(w2>0));
w1:=l2.a*ap1.x+l2.b*ap1.y+l2.c;
w2:=l2.a*ap2.x+l2.b*ap2.y+l2.c;
res:=res and (((w1>0)and(w2<0))or((w1<0)and(w2>0)));
CheckIntersect:=not res;
end;
function CheckPolygons(p1,p2:point):boolean;
var i,j:integer;
res:boolean;
begin
res:=true;
for i:=1 to l do
begin
for j:=1 to polygons[i].n do
begin
res:=res and CheckIntersect(p1,p2,polygons[i].v[j],polygons[i].v[(j mod polygons[i].n)+1]);
if not res then
break;
end;
if not res then
break;
end;
CheckPolygons:=res;
end;
procedure BuildGraph;
var i,j,ti,tj,s:integer;
begin
n:=0;
for i:=1 to l do
for j:=1 to polygons[i].n do
begin
inc(n);
s:=0;
for ti:=1 to l do
for tj:=1 to polygons[ti].n do
begin
inc(s);
if CheckPolygons(polygons[i].v[j],polygons[ti].v[tj]) then
g[n,s]:=sqrt(sqr(polygons[i].v[j].x-polygons[ti].v[tj].x)+
sqr(polygons[i].v[j].y-polygons[ti].v[tj].y))
else
g[n,s]:=-1;
g[s,n]:=g[n,s];
end;
end;
inc(n);
s:=0;
for ti:=1 to l do
for tj:=1 to polygons[ti].n do
begin
inc(s);
if CheckPolygons(pstart,polygons[ti].v[tj]) then
g[n,s]:=sqrt(sqr(pstart.x-polygons[ti].v[tj].x)+
sqr(pstart.y-polygons[ti].v[tj].y))
else
g[n,s]:=-1;
g[s,n]:=g[n,s];
end;
inc(n);
s:=0;
for ti:=1 to l do
for tj:=1 to polygons[ti].n do
begin
inc(s);
if CheckPolygons(pend,polygons[ti].v[tj]) then
g[n,s]:=sqrt(sqr(pend.x-polygons[ti].v[tj].x)+
sqr(pend.y-polygons[ti].v[tj].y))
else
g[n,s]:=-1;
g[s,n]:=g[n,s];
end;
end;
procedure Relax(u,v:integer);
begin
if g[u,v]>0 then
if (d[v]>d[u]+g[u,v])or(d[v]<0) then
d[v]:=d[u]+g[u,v];
end;
procedure Dijkstra;
var i,j,now,k:integer;
min:extended;
us:array[1..maxn]of boolean;
begin
for i:=1 to n do
begin
d[i]:=-1; us[i]:=false;
end;
d[n-1]:=0;
now:=n-1;
for i:=1 to n-1 do
begin
us[now]:=true; min:=-1;
for j:=1 to n do
if not us[j] then
begin
Relax(now,j);
if ((min<0)or(min>d[j]))and(d[j]>0) then
begin
min:=d[j]; k:=j;
end;
end;
now:=k;
end;
end;
procedure Solve;
begin
BuildGraph;
Dijkstra;
end;
procedure WriteResult;
begin
write(d[n]);
end;
begin
Init;
Solve;
WriteResult;
end.MESSAGE
{$A+,B-,D-,E+,F-,G+,I-,L-,N+,O-,P-,Q-,R-,S-,T-,V+,X+,Y-}
program message;
const maxn=20100;
var s:array[1..maxn]of char;
len:array[1..maxn]of integer;
res,n,n1:integer;
procedure Init;
var i:integer;
begin
i:=0;
while not eoln do
begin
inc(i);
read(s[i]);
end;
readln;
n:=i;
inc(i); s[i]:=#0;
while not eoln do
begin
inc(i);
read(s[i]);
end;
res:=0;
n1:=i;
end;
procedure Solve;
var i,j,x:integer;
begin
for i:=1 to n do
begin
len[i]:=0;
for j:=i+1 to n1 do
begin
x:=len[j-1];
while (s[x+i]<>s[j])and(x>0) do
x:=len[x+i-1];
if s[x+i]=s[j] then
len[j]:=x+1
else
len[j]:=0;
if (len[j]>res)and(j>n) then
res:=len[j];
end;
end;
end;
procedure WriteResult;
begin
writeln(res);
end;
begin
Init;
Solve;
WriteResult;
end.Поза форумом
NewDomino O(N*K)
DSP2 O(N^3)
Army O(N*K*log(N))
Дерево отрезков.... Уверен, что быстрее решения - нету. У кого за О(N) могу поздравить !!! Просто если K=1 , то эта задача про инверсии, для которой минимум - O(Nlog(N))
Lake O(V^3)
Батыев Андрей обрати внимание на свои 3 вложенных цикла по V. Сложно такое назвать O(V^2).
Message O(n)
Кто хочет решить линейно может копать инфу по дереву или же массиву суффиксов, короче все что связано с суффиксами.
Відредаговано Vladislav Simonenko (2006-01-19 15:59:51)
Поза форумом
Vova написав:
Army
Читаем v<=(номер 1-ого солдата), запоминаем min:=v далее в строю ниже него (op:=v-1) солдат, значит выбрать K солдат можно C(N-op-1, K) способами (C(M,N) - количество способов выбрать из M по N элементов, C(M,N)=m!/(n!(m-n)!))
...
Если я правильно понял условие, то то, что ты здесь написал - неправильно. Пример: 3 2 1 3 2. Твоя прога выводит 1. Правильный ответ - 0.
Поза форумом
Rybak написав:
Vova написав:
Army
Читаем v<=(номер 1-ого солдата), запоминаем min:=v далее в строю ниже него (op:=v-1) солдат, значит выбрать K солдат можно C(N-op-1, K) способами (C(M,N) - количество способов выбрать из M по N элементов, C(M,N)=m!/(n!(m-n)!))
...Если я правильно понял условие, то то, что ты здесь написал - неправильно. Пример: 3 2 1 3 2. Твоя прога выводит 1. Правильный ответ - 0.
Согласен. Твоя прога действительно работает неправильно даже на самых простых тестах (проверил еще вчера
)))
Поза форумом
Значит мне не повезло ![]()
хотел как лучше, а получилось как всегда.
Поза форумом
xXx написав:
Message - O(log(min(Length(S1),Length(S2)))*(Length(S1)+Length(S2))
Объясни как
Поза форумом
Привет всем!
Лично я решал задачи так:
NewDomino - O(K) - цикл Эйлера.
DSP2 - O(n^3) - ДП.
Army - O(k*n*log(n)) - Использовал сортировку слиянием.
Lake - O(n^3) - Алгоритм Флойда (Те которые медленее нет смысла использовать, т. к. создать матрицу смежности быстрее чем за O(n^3) я не знаю как).
Message - O(n*m) - Я ни чего не придумал быстрее. Интересно узнать более эффективные алгоритмы, где можно о них узнать?
Поза форумом
Victor Barinov написав:
Message - O(n*m) - Я ни чего не придумал быстрее. Интересно узнать более эффективные алгоритмы, где можно о них узнать?
Я уже писал что надо использовать дерево суффиксов. У меня решение за O(N). Могу разместить исходник, но думаю толку не будет. Лучше поискать доку, желательно на английском языке( Suffix Trees ).
Good Luck !!!
Відредаговано Vladislav Simonenko (2006-01-19 20:08:34)
Поза форумом
Ура Онлайн Работает на всех тэстах!!!!!!!!!!!!!!!!!!![]()

Поза форумом
NewDomino
#define NetOI
#include<stdio.h>
#define AddEdge(a,b,n)\
if(A[a][b]==0){\
Adj[a][++*Adj[a]]=b;\
Adj[b][++*Adj[b]]=a;\
}\
A[a][b]+=n;\
A[b][a]+=n;\
C[a]=!C[a];\
C[b]=!C[b]
#define AddVertex(v)\
if(HVI[v]==-1){\
HV[VN]=v;\
HVI[v]=VN++;\
}\
v=HVI[v]
char HVI[51];
char HV[50],VN;
bool C[50];
short A[50][50],N;
char R[1002];
short RN=0;
char Adj[50][51];
void Search(char v){
static char vi;
char i=1;
for(;i<=*Adj[v];i++){
vi=Adj[v][i];
while(A[v][vi]){
A[v][vi]--;
A[vi][v]--;
N--;
Search(vi);
vi=Adj[v][i];
}
}
R[RN++]=v;
}
int main(){
#ifndef NetOI
*stdin=*fopen("NewDomino.in","r");
#endif
scanf("%d",&N);
short i=0,a,b;
for(;i<=50;i++)
HVI[i]=-1;
for(i=0;i<N;i++){
scanf("%d%d",&a,&b);
AddVertex(a);
AddVertex(b);
AddEdge(a,b,1);
}
for(i=0;i<VN;i++)
if(C[i])
goto NA;
Search(0);
if(N||R[0]!=R[RN-1]){
NA:
printf("-1");
}else
for(RN-=2;RN>=0;RN--)
printf("%d %d ",int(HV[R[RN+1]]),int(HV[R[RN]]));
#ifndef NetOI
fclose(stdin);
#endif
return 0;
}DSP2
#define NetOI
#include<stdio.h>
#define swap(a,b) a=(a^=b)^(b^=a)
short N,x[53];
unsigned long R[52][52];
int main(){
#ifndef NetOI
*stdin=*fopen("DSP2.in","r");
#endif
scanf("%d%d",x+52,&N);
short i=1;
for(N++;i<N;i++)
scanf("%d",&x[i]);
x[N]=x[52];
short j;
short in,n=N-1,k;
unsigned long m;
for(i=1;i<n;i++){
k=i+1;
for(j=k+1;j<=n;j++)
if(x[j]<x[k])
k=j;
if(x[k]<x[i])
swap(x[k],x[i]);
}
for(i=1,j=1;i<=N;i++)
if(x[i]!=x[i-1])
x[j++]=x[i];
n=(N=j-1)-1;
switch(N) {
case 0:
printf("%d","0");
break;
case 1:
printf("%d",x[n]);
break;
default:
for(i=N-2;i>=0;i--)
R[i][i+2]=x[i+2]-x[i];
for(j=3;j<=N;j++)
for(i=0;i<=N-j;i++){
R[i][n=(in=i+j)]=-1;in-=1;
for(k=i+1;k<=in;k++){
m=R[i][k]+R[k][n];
if(m<R[i][n])R[i][n]=m;
}R[i][n]+=x[n]-x[i];
}
printf("%lu",R[0][N]);
}
#ifndef NetOI
fclose(stdin);
#endif
return 0;
}Army
#define NetOI
#include<stdio.h>
long a[100000],b[100000],n,m;
long long f[2][100000];
char c[100000];
#define f(i) f[J][i]
#define g(i) f[K][i]
#define SwapLayers K=J,J^=1
#define swap(a,b) a=(a^=b)^(b^=a)
#define sgn(a) (a<0?-1:1)
#define min(a,b) (a<b?a:b)
#define rN 13
#define abs(a) (a<0?-a:a)
short J=1,K=0,y=1;
long long r[rN];
long long F(int x){
short i=0;
long x0=x-1;
long d,min,max;
if((d=a[x]-a[x0])>0)
r[0]=g(x0);
else r[0]=0;
max=abs(d);
if(max==1)
return f(x0)+r[0];
min=0;
for(i=1;i<rN;i++){
if((d=a[x]-a[x0-i])>0) r[i]=r[i-1]+g(x0-i);
else {
r[i]=r[i-1];d=-d;
}
if(d==1)return f(x0-i)+r[i];
if(d<max){
max=d;
min=i;
}
}
i=min;
x0-=i;
min=a[x0];
max=a[x];
if(min>max)
swap(min,max);
long long R=0;
long j=min+1;
for(min=y-1;j<max;j++)
if(b[j]<x0&&b[j]>=min)
R+=g(b[j]);
if(a[x0]>a[x])
R=-R;
R+=f(x0);
return r[i]+R;
}
bool CalcC(){
long l,r,k,i,R=1,p[12];
c[0]=1;
for(p[1]=0,i=1;i<n;i++){
l=1;r=R;
while(l<=r)
if(a[p[k=(l+r)/2]]>a[i])r=k-1;
else l=k+1;
if(r<11)
r++;
if(r>R)
p[R=r]=i;
else if(a[i]<a[p[r]])
p[r]=i;
c[i]=r;
}
if(R<=m)
return false;
return true;
}
int main(){
#ifndef NetOI
*stdin=*fopen("Army.in","r");
#endif
scanf("%ld%ld",&n,&m);
long i=0,t;
for(;i<n;i++){
scanf("%ld",a+i);
b[--a[i]]=i;
f[0][i]=1;
}
if(CalcC()){
long long R;
for(;y<=m;y++,SwapLayers){
for(i=min(y+rN,n)-1;i>=y;i--){
if(c[i]>y){
for(R=0,t=y-1;t<i;t++)
if(a[t]<a[i])
R+=g(t);
f(i)=R;
}else f(i)=0;
}
for(i=y+rN;i<n;i++)
if(c[i]>y)
f(i)=F(i);
else f(i)=0;
}
if(c[m]>m)
R=g(m);
else R=0;
for(i=m+1;i<n;i++)
if(c[i]>m)
R+=g(i);
printf("%I64d",R);
}else printf("0");
#ifndef NetOI
fclose(stdin);
return 0;
#endif
}Lake
#define NetOI
#include<stdio.h>
#include<math.h>
#define sqr(a) (a)*(a)
#define S(x0,y0,x1,y1) sqrt(sqr((x1)-(x0))+sqr((y1)-(y0)))
#define S2(x0,y0,x1,y1) (sqr((x1)-(x0))+sqr((y1)-(y0)))
#define Eps 1E-16
#define Eps2 1E-8
#define MaxPath 1E9
const long double PI=3.1415926535897932384626433832795;
struct Point{
double x,y;
};
inline bool CrossLine(double x0,double y0,double x1,double y1,double x2,double y2,double x3,double y3){
double a0=y1-y0,b0=x0-x1,c0=-(x0*a0+y0*b0),
a2=y3-y2,b2=x2-x3,c2=-(x2*a2+y2*b2);
#define f0(x,y) (a0*x+b0*y+c0)
#define f2(x,y) (a2*x+b2*y+c2)
return (f0(x2,y2)*f0(x3,y3)<=-Eps && f2(x0,y0)*f2(x1,y1)<=-Eps);
#undef f0
#undef f2
}
class Polygon{
private:
template<class T>
static T Abs(T a){
return (a<0?-a:a);
}
public:
double x,y;
Point p[20];
double r,R;
short n;
void Read(){
scanf("%d%lf%lf%lf%lf",&n,&x,&y,&p[0].x,&p[0].y);
short i=1;
R=S(x,y,p[0].x,p[0].y);
double A=atan2(p[0].x-x,p[0].y-y),dA=2*PI/n;
for(;i<n;i++){
p[i].x=x+cos(A+dA*i)*R;
p[i].y=y+sin(A+dA*i)*R;
}
double tX=(p[1].x+p[0].x)/2-x,tY=(p[1].y+p[0].y)/2-y;
r=sqrt(tX*tX+tY*tY);
}
bool Cross(double x0,double y0,double x1,double y1){
double a=y1-y0,b=x0-x1,c=-(x0*a+y0*b);
double C2=a*a+b*b;
double H=(a*x+b*y+c)/sqrt(C2);
if(H<0)H=-H;
double L0=S2(x,y,x0,y0);
double L1=S2(x,y,x1,y1);
if(C2<Abs(L1-L0)+Eps2 && L0+Eps2>=R*R && L1+Eps2>=R*R)
return false;
if(H+Eps>R)
return false;
if(H<r-Eps)
return true;
short i=0;
for(i=1;i<n;i++)
if(::CrossLine(x0,y0,x1,y1,p[i].x,p[i].y,p[i-1].x,p[i-1].y))
return true;
return false;
}
}P[10];
short N,VN=2;
unsigned char *Adj[202];
unsigned char C[202];
#define AddEdge(v,e) Adj[v][C[v]++]=e
Point* p[202],CP[2];
double S[202];
bool VerifyLine(double x0,double y0,double x1,double y1){
short i=0;
for(;i<N;i++)
if(P[i].Cross(x0,y0,x1,y1))
return false;
return true;
}
inline void Relax(unsigned char i,unsigned char j){
double L=S[i]+S(p[i]->x,p[i]->y,p[j]->x,p[j]->y);
if(S[j]>L)S[j]=L;
}
int main(){
#ifndef NetOI
*stdin=*fopen("Lake.in","r");
#endif
scanf("%lf%lf%lf%lf%d",&CP[0].x,&CP[0].y,&CP[1].x,&CP[1].y,&N);
short i,j,k,LN;
for(i=0;i<N;){
P[i].Read();
if(P[i].R>=Eps)
i++;
else N--;
}
for(i=0;i<202;Adj[i++]=new unsigned char[202])
p[0]=&CP[0];
p[1]=&CP[1];
if(VerifyLine(p[0]->x,p[0]->y,p[1]->x,p[1]->y))
printf("%.16lf",double(S(p[0]->x,p[0]->y,p[1]->x,p[1]->y)));
else{
for(i=0;i<N;i++)
for(j=0,LN=VN;j<P[i].n;j++,VN++){
p[VN]=&P[i].p[j];
k=LN+(j+1)%P[i].n;
AddEdge(VN,k);
AddEdge(k,VN);
for(k=0;k<LN;k++)
if(VerifyLine(p[VN]->x,p[VN]->y,p[k]->x,p[k]->y)){
AddEdge(VN,k);
AddEdge(k,VN);
}
}
VN--;
for(S[0]=0,i=1;i<=VN;S[i++]=MaxPath);
unsigned char Q[202],T;
for(T=0;T<VN;T++)
Q[T]=T+1;
for(i=0;i<C[0];i++)
Relax(0,Adj[0][i]);
unsigned char MinI;
for(;T;Q[MinI]=Q[--T]){
MinI=0;
for(i=1;i<T;i++){
if(S[Q[i]]<S[Q[MinI]])
MinI=i;
}
i=Q[MinI];
for(j=0;j<C[i];j++)
Relax(i,Adj[i][j]);
}
if(S[1]<MaxPath)
printf("%.lf",S[1]);
else printf("-1");
}
#ifndef NetOI
fclose(stdin);
#endif
for(i=0;i<VN;i++)
delete Adj[i];
return 0;
}Message
#define NetOI
#include<stdio.h>
short aN=0,bN=0;
unsigned char *a=new unsigned char[10001],*b=new unsigned char[10001];
short SSS=0;
#define q 32768
#define fq(v) ((v)%q)
#define p 53
short *L=new short[q],
*Ta=new short[10000],
*Tb=new short[10000];
long P;
#define T0(T0,Ai) fq(fq(long(T0)*p)+Ai)
#define Ti(Ti1,Ai1,Aid1) fq(fq(p*long(Ti1))+fq(q-fq(long(Ai1)*P))+Aid1)
inline bool F(short d){
short i,Na=aN-d+1,Nb=bN-d+1;
for(i=0,P=1;i<d;i++)
P=fq(P*p);
Ta[0]=0;
for(i=0;i<d;i++)
Ta[0]=T0(Ta[0],a[i]);
L[Ta[0]]=-1;
for(Na--,i=0;i<Na;i++)
L[Ta[i+1]=Ti(Ta[i],a[i],a[i+d])]=-1;
Tb[0]=0;
for(i=0;i<d;i++)
Tb[0]=T0(Tb[0],b[i]);
L[Tb[0]]=-1;
for(Nb--,i=0;i<Nb;i++)
L[Tb[i+1]=Ti(Tb[i],b[i],b[i+d])]=-1;
short t;
for(i=0;i<=Na;i++){
t=Ta[i];
Ta[i]=L[t];
L[t]=i;
}
short j,k;
for(j=0;j<=Nb;j++)
for(i=L[Tb[j]];i>=0;i=Ta[i]){
for(k=0;a[i+k]==b[j+k]&&k+i<aN&&k+j<bN;k++);
if(k>=d){
SSS=k;
return true;
}
}
return false;
}
int main(){
#ifndef NetOI
*stdin=*fopen("Message.in","r");
#endif
gets((char*)a);
gets((char*)b);
for(;a[aN];aN++);
for(;b[bN];bN++);
short L=1,R=(aN<bN?aN:bN),D;
do {
if(F(D=(L+R)/2))
L=SSS+1;
else
R=D-1;
} while(L<=R);
printf("%d",SSS);
#ifndef NetOI
fclose(stdin);
#endif
delete[] a,b,L,Ta,Tb;
return 0;
}Відредаговано xXx (2006-01-20 01:30:21)
Поза форумом
Victor Barinov написав:
Привет всем!
Лично я решал задачи так:
...
Lake - O(n^3) - Алгоритм Флойда (Те которые медленее нет смысла использовать, т. к. создать матрицу смежности быстрее чем за O(n^3) я не знаю как).
...
Алгоритм Флойда находит кратчайшие пути между всеми парами вершин... Для решения данной задачи следует использовать алгоритм Дейкстры, сложность которого - O(V*O(ExtMin)+E*O(Add)), где V - кол. вершин, E - кол. рёбер, O(ExtMin) - сложность извлеченя минимального елемента множества, O(Add) - сложность добавления(или изменения значения) елемента множества...
Поза форумом
Vladislav Simonenko написав:
...
Дерево отрезков.... Уверен, что быстрее решения - нету. У кого за О(N) могу поздравить !!! Просто если K=1 , то эта задача про инверсии, для которой минимум - O(Nlog(N))
...
Не совсем, если K=1, то задача сводиться к задаче о нахождении числа инверсий в массиве, все елементы которого разлиичные натуральные числа, не превосходящие N... В своём решении я использовал именно этот факт...
Поза форумом
А вот мои решения:
Newdomino:
#include <iostream>
using namespace std;
const int maxN=50;
const int maxK=1000;
struct edge
{
int w;
edge *next,*prv,*dup;
};
edge domino[maxN];
edge edgs[maxK*2];
int edgCnt=0;
int stk[maxK+5];
int stkPtr;
int path[maxK+5];
int pathCnt;
inline void AddEdge(int v,int w)
{
edgs[edgCnt].w=w;
edgs[edgCnt].next=domino[v].next;
edgs[edgCnt].prv=&domino[v];
domino[v].next=&edgs[edgCnt++];
if(domino[v].next->next)domino[v].next->next->prv=domino[v].next;
edgs[edgCnt].w=v;
edgs[edgCnt].next=domino[w].next;
edgs[edgCnt].prv=&domino[w];
domino[w].next=&edgs[edgCnt++];
if(domino[w].next->next)domino[w].next->next->prv=domino[w].next;
edgs[edgCnt-1].dup=&edgs[edgCnt-2];
edgs[edgCnt-2].dup=&edgs[edgCnt-1];
}
inline void RemEdge(edge *e)
{
e->prv->next=e->next;
if(e->next)e->next->prv=e->prv;
e=e->dup;
e->prv->next=e->next;
if(e->next)e->next->prv=e->prv;
}
inline void GoEuler(int v)
{
int w;
while(domino[v].next)
{
w=domino[v].next->w;
RemEdge(domino[v].next);
stk[stkPtr++]=w;
v=w;
}
}
int BuildEuler(int k)
{
int i;
for(i=0;i<maxN&&!domino[i].next;i++);
stk[0]=i;
stkPtr=1;
do{
GoEuler(stk[stkPtr-1]);
path[pathCnt++]=stk[--stkPtr];
}while(stkPtr);
return pathCnt==k+1&&path[0]==path[pathCnt-1];
}
int main()
{
int i,k,v,w;
cin>>k;
for(i=0;i<k;i++)
{
cin>>v>>w;
v--;
w--;
AddEdge(v,w);
}
if(BuildEuler(k))
{
cout<<path[0]+1;
for(i=1;i<pathCnt-1;i++)
cout<<" "<<path[i]+1<<" "<<path[i]+1;
cout<<" "<<path[pathCnt-1]+1<<endl;
}
else cout<<-1<<endl;
return 0;
}Dsp2
#include <iostream>
#include <climits>
using namespace std;
const int maxN=50;
int main()
{
int i,n,l,j;
int saws[maxN+2];
int cost[maxN+2][maxN+2]={0};
cin>>l>>n;
saws[0]=0;
saws[n+1]=l;
for(i=1;i<=n;i++)
cin>>saws[i];
for(l=2;l<=n+1;l++)
for(i=0;i+l<n+2;i++)
{
for(j=1,cost[i][i+l]=INT_MAX;j<l;j++)
if(cost[i][i+l]>cost[i][i+j]+cost[i+j][i+l])
cost[i][i+l]=cost[i][i+j]+cost[i+j][i+l];
cost[i][i+l]+=saws[i+l]-saws[i];
}
cout<<cost[0][n+1]<<endl;
return 0;
}Army:
#include <iostream>
using namespace std;
const int maxN=100000;
const int maxK=11;
const int maxNodes=265000;
struct node
{
unsigned long long count;
int a,b;
node *left,*right;
};
int height[maxN];
node nodes[maxNodes];
unsigned long long counts[maxN];
node *tree;
int nCnt=0;
node *buildTree(register int a,register int b)
{
register int mid;
node *curr=&nodes[nCnt++];
curr->a=a;
curr->b=b;
if(a<b)
{
mid=(a+b)/2;
curr->left=buildTree(a,mid);
curr->right=buildTree(mid+1,b);
}
return curr;
}
inline void UpdateTree(register node *curr,register int x,register unsigned long long c)
{
if(c)
while(curr)
{
curr->count+=c;
if(curr->left&&x<=curr->left->b)curr=curr->left;
else curr=curr->right;
}
}
inline unsigned long long FindSegment(register node *curr,register int b)
{
register unsigned long long res=0;
while(curr&&curr->count)
{
if(curr->left&&b>=curr->left->b)
{
res+=curr->left->count;
curr=curr->right;
}
else curr=curr->left;
}
return res;
}
int main()
{
register int n;
int k;
register int i;
register unsigned long long cnt;
cin>>n>>k;
for(i=0;i<n;i++)
cin>>height[i];
for(i=0;i<n;i++)
counts[i]=1;
//building tree
nCnt=0;
tree=buildTree(1,n);
for(;k;k--)
{
// rebuilding tree
for(i=0;i<nCnt;i++)
tree[i].count=0;
// main cycle
for(i=0;i<n;i++)
{
UpdateTree(tree,height[i],counts[i]);
counts[i]=FindSegment(tree,height[i]-1);
}
}
for(i=0,cnt=0;i<n;i++)
cnt+=counts[i];
cout<<cnt<<endl;
return 0;
}Lake:
#include <iostream>
#include <cmath>
using namespace std;
const int maxLakes=10;
const int maxLakeV=20;
const double HugeVal=1e100;
const double eps=0.0000001;
const int maxV=2+maxLakes*maxLakeV;
const int IvanV=0;
const int HouseV=1;
struct point
{
double x,y;
inline point operator-(const point &p)const
{
point ans;
ans.x=x-p.x;
ans.y=y-p.y;
return ans;
}
inline point operator+(const point &p)const
{
point ans;
ans.x=x+p.x;
ans.y=y+p.y;
return ans;
}
inline double operator*(const point &p)const//vector multiple
{
return x*p.y-p.x*y;
}
};
istream &operator>>(istream &is,point &p)
{
return is>>p.x>>p.y;
}
struct node
{
int p;
node *next;
};
double lengths[maxV][maxV];
point points[maxV];
int lakeInd[maxV];
node *lakes[maxLakes];
node nds[maxV+maxLakes];
int nCnt=0;
int lCnt=0;
int pCnt=0;
inline double length(point p1,point p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
inline void ProcLake(int sides,point center,point first)
{
const double PiX2=2*M_PI;
double alpha,r,phi0;//alpha - phi2-phi1
register int i,j;
int firstind;
node *nd;
alpha=PiX2/sides;
r=length(center,first);
nds[nCnt].p=pCnt;
nds[nCnt].next=0;
lakes[lCnt]=&nds[nCnt++];
lakeInd[pCnt]=lCnt;
points[firstind=pCnt++]=first;
first=first-center;
phi0=atan2(first.y,first.x);
for(i=1;i<sides;i++)
{
first.x=r*cos(alpha*i+phi0);
first.y=r*sin(alpha*i+phi0);
nds[nCnt].p=pCnt;
nds[nCnt].next=lakes[lCnt];
lakes[lCnt]=&nds[nCnt++];
lakeInd[pCnt]=lCnt;
points[pCnt++]=first+center;
}
nds[nCnt].p=firstind;
nds[nCnt].next=lakes[lCnt];
lakes[lCnt]=&nds[nCnt++];
for(i=firstind;i<pCnt;i++)
for(j=firstind;j<pCnt;j++)
lengths[i][j]=HugeVal;
for(nd=lakes[lCnt];nd->next;nd=nd->next)
lengths[nd->p][nd->next->p]=lengths[nd->next->p][nd->p]=length(points[nd->p],points[nd->next->p]);
lCnt++;
}
inline int SideFromVector(const point &ab,const point &ac)
{
double mult;
mult=ab*ac;
if(mult>eps)return 1;
else if(mult<-eps)return -1;
else return 0;
}
inline int PointOnLine(const point &a,const point &b,const point &c)
{
return SideFromVector(b-a,c-a)==0&&
(a.x-c.x>=-eps&&b.x-c.x<=eps||
b.x-c.x>=-eps&&a.x-c.x<=eps)&&
(a.y-c.y>=-eps&&b.y-c.y<=eps||
b.y-c.y>=-eps&&a.y-c.y<=eps);
}
inline int IntersectLake(point a,point b,int l)
{
register node *nd;
register int OnLine=0;
register point ab=b-a;
point cd;
int sign;
for(nd=lakes[l];nd->next&&OnLine<2;nd=nd->next)
{
const point &c=points[nd->p];
const point &d=points[nd->next->p];
OnLine+=PointOnLine(a,b,c);
if(SideFromVector(ab,c-a)*SideFromVector(ab,d-a)<0)
OnLine+=SideFromVector(cd=d-c,a-c)*SideFromVector(cd,b-c)<=0;
}
return OnLine>1;
}
inline int GoodEdge(int v,int w)
{
register int k;
for(k=0;k<lCnt;k++)
if(IntersectLake(points[v],points[w],k))return 0;
return 1;
}
void BuildAdjMatrix()
{
register int i,j;
for(i=0;i<pCnt;i++)
lengths[i][i]=0.0;
for(i=0;i<pCnt-1;i++)
for(j=i+1;j<pCnt;j++)
if(lakeInd[i]!=lakeInd[j])
{
if(GoodEdge(i,j))
lengths[i][j]=lengths[j][i]=length(points[i],points[j]);
else lengths[i][j]=lengths[j][i]=HugeVal;
}
}
double GetLengthFromIvanToHome()
{
double toV[maxV];
char visited[maxV];
register int i,shortest;
for(i=0;i<pCnt;i++)
{
visited[i]=0;
toV[i]=HugeVal;
}
toV[IvanV]=0;
do{
for(shortest=-1,i=0;i<pCnt;i++)
if(!visited[i]&&(shortest<0||toV[shortest]>toV[i]))
shortest=i;
visited[shortest]=1;
for(i=0;i<pCnt;i++)
if(toV[i]>toV[shortest]+lengths[shortest][i])
toV[i]=toV[shortest]+lengths[shortest][i];
}while(!visited[HouseV]);
return toV[HouseV];
}
int main()
{
register int n,i,sides;
point center,first;
cin>>points[0]>>points[1]>>n;
pCnt=2;
lakeInd[0]=-1;
lakeInd[1]=-2;
for(i=0;i<n;i++)
{
cin>>sides>>center>>first;
ProcLake(sides,center,first);
}
BuildAdjMatrix();
cout<<GetLengthFromIvanToHome()<<endl;
return 0;
}Message:
#include <iostream>
#include <cstring>
using namespace std;
const int maxL=10000;
const int Base=257;
const int Mod=299993;
struct hash_el
{
hash_el *next;
char *str;
};
hash_el hashes[maxL];
hash_el *table[Mod];
char strA[maxL+1];
char strB[maxL+1];
int lenA,lenB;
inline int checkPos(char *str,int hash,int len)
{
int i;
hash_el *l;
for(l=table[hash];l;l=l->next)
{
for(i=0;i<len&&l->str[i]==str[i];i++);
if(i==len)return 1;
}
return 0;
}
inline int check(int len)
{
int i;
int hash,maxdigpow,found;
for(i=0;i<Mod;i++)
table[i]=0;
for(i=0,hash=0,maxdigpow=1;i<lenA;i++)
{
hash=(Base*hash+strA[i])%Mod;
if(i<len)maxdigpow=(maxdigpow*Base)%Mod;
else hash=(hash+Mod-maxdigpow*strA[i-len]%Mod)%Mod;
if(i>=len-1)
{
hashes[i].str=strA+i-len+1;
hashes[i].next=table[hash];
table[hash]=&hashes[i];
}
}
for(i=0,hash=0,found=0;i<lenB&&!found;i++)
{
hash=(Base*hash+strB[i])%Mod;
if(i>=len)hash=(hash+Mod-maxdigpow*strB[i-len]%Mod)%Mod;
if(i>=len-1)found=checkPos(strB+i-len+1,hash,len);
}
return found;
}
inline int findMaxSubStrLen()
{
int min,max,mid;
for(min=0,max=(lenA<lenB?lenA:lenB);min<max;)
{
mid=(min+max)/2+1;
if(check(mid))min=mid;
else max=mid-1;
}
return max;
}
int main()
{
cin.getline(strA,sizeof strA);
cin.getline(strB,sizeof strB);
lenA=strlen(strA);
lenB=strlen(strB);
cout<<findMaxSubStrLen()<<endl;
return 0;
}Поза форумом
Вот мои решения. newdomino - 1 BD. dsp2 - AC. army - AC. lake - 1 TL. message - 2 WA. Все остальное PASSED.
newdomino:
{$APPTYPE CONSOLE}
{$B-,R-}
const
maxn=50;
maxk=1000;
var
a:array[1..maxn,1..maxn] of smallint;
num:array[1..maxn] of smallint;
st:array[1..maxk+2] of byte;
numst,numpath:smallint;
n,k,i,aa,bb,tek:smallint;
path:array[1..maxk+2] of byte;
procedure Search(ver:byte);
var
i:byte;
begin
i:=1;
while (i<=n)and(a[ver,i]=0)do inc(i);
if i<=n then
begin
dec(a[ver,i]);
dec(a[i,ver]);
inc(numst);
st[numst]:=i;
Search(i);
end;
end;
begin
fillchar(a,sizeof(a),0);
fillchar(num,sizeof(num),0);
n:=0;
read(k);
for i:=1 to k do
begin
read(aa,bb);
if aa>n then n:=aa;
if bb>n then n:=bb;
inc(num[aa]);
inc(num[bb]);
inc(a[aa,bb]);
inc(a[bb,aa]);
end;
for i:=1 to n do if odd(num[i]) then
begin
writeln(-1);
halt;
end;
tek:=1;
while num[tek]=0 do inc(tek);
numst:=0;
numpath:=0;
inc(numst);
st[numst]:=tek;
while numst>0 do
begin
tek:=st[numst];
Search(tek);
inc(numpath);
path[numpath]:=tek;
dec(numst);
end;
write(path[1]);
for i:=2 to numpath-1 do write(' ',path[i],' ',path[i]);
writeln(' ',path[numpath]);
end.dsp2:
{$APPTYPE CONSOLE}
{$B-,R-}
const
maxn=50;
nv=1000000;
var
a:array[1..maxn+2] of smallint;
f:array[1..maxn+2,1..maxn+2] of longint;
l,n,i,j:smallint;
procedure calc(i,j:byte);
var
k:byte;
tek:longint;
begin
if f[i,j]<>nv then exit;
for k:=i+1 to j-1 do
begin
if f[i,k]=nv then calc(i,k);
if f[k,j]=nv then calc(k,j);
tek:=f[i,k]+f[k,j]+a[j]-a[i];
if tek<f[i,j] then f[i,j]:=tek;
end;
end;
begin
a[1]:=0;
read(l,n);
for i:=1 to n do read(a[i+1]);
inc(n);
a[n+1]:=l;
inc(n);
for i:=1 to n do
for j:=1 to n do
f[i,j]:=nv;
for i:=1 to n do f[i,i]:=0;
for i:=1 to n-1 do f[i,i+1]:=0;
calc(1,n);
writeln(f[1,n]);
end.army:
{$APPTYPE CONSOLE}
{$B-,R-}
{$MAXSTACKSIZE $01000000}
const
maxn=100000;
maxtree=300000;
maxk=11;
type
treeel=record
a,b:longint;
count:int64;
left,right:longint;
end;
var
i,n,h:longint;
j,k:byte;
height:array[1..maxn] of longint;
ans:array[1..maxn] of int64;
res:int64;
tree:array[1..maxtree] of treeel;
function BuildTree(a,b:longint):longint;
var
mid,tekh:longint;
begin
inc(h);
tekh:=h;
tree[tekh].a:=a;
tree[tekh].b:=b;
if a<b then
begin
mid:=(a+b)div 2;
tree[tekh].left:=BuildTree(a,mid);
tree[tekh].right:=BuildTree(mid+1,b);
end;
BuildTree:=tekh;
end;
procedure UpdateTree(tek:longint;index:longint;c:int64);
var
mid:longint;
begin
if c<>0 then
while tek<>0 do
begin
inc(tree[tek].count,c);
mid:=(tree[tek].a+tree[tek].b) div 2;
if index<=mid then tek:=tree[tek].left else tek:=tree[tek].right;
end;
end;
function Num(tek,h:longint):int64;
var
ans:int64;
mid:longint;
begin
ans:=0;
while (tek<>0)and(tree[tek].count<>0) do
begin
mid:=(tree[tek].a+tree[tek].b) div 2;
if h>=mid then
begin
inc(ans,tree[tree[tek].left].count);
tek:=tree[tek].right;
end else tek:=tree[tek].left;
end;
Num:=ans;
end;
begin
read(n,k);
for i:=1 to n do read(height[i]);
if k+1>n then
begin
writeln(0);
halt;
end;
h:=0;
fillchar(tree,sizeof(tree),0);
BuildTree(1,n);
for i:=1 to n do ans[i]:=1;
for j:=1 to k do
begin
for i:=1 to h do tree[i].count:=0;
for i:=1 to n do
begin
UpdateTree(1,height[i],ans[i]);
ans[i]:=Num(1,height[i]-1);
end;
end;
res:=0;
for i:=1 to n do inc(res,ans[i]);
writeln(res);
end.lake:
{$APPTYPE CONSOLE}
{$B-,R-,N+}
const
maxlake=10;
maxver=20;
maxn=maxlake*maxver+2;
delta=1e-9;
nv=1e9;
type
point=record
x,y:extended;
end;
lake=record
n:byte;
v:array[1..maxver+2] of point;
end;
var
ver:array[1..maxn] of point;
a:array[1..maxn,1..maxn] of extended;
f:array[0..maxn] of extended;
stver,endver,zentr,pp,next:point;
ang:extended;
numlake,numver,i,j,k,l,{s,}x,y,n:byte;
mnog:array[1..maxlake+2] of lake;
v1,v2,v3:point;
flag:boolean;
sign1,sign2:shortint;
p1,p2,zn:boolean;
q:array[1..maxn] of byte;
min,numzero:byte;
function sign(a:extended):shortint;
begin
if abs(a)<delta then sign:=0 else
if a>0 then sign:=1 else
{if a<0 then }sign:=-1;
end;
begin
for i:=1 to maxn do
for j:=1 to maxn do
a[i,j]:=nv;
n:=0;
read(stver.x,stver.y,endver.x,endver.y);
read(numlake);
for i:=1 to numlake do
begin
read(numver);
mnog[i].n:=numver;
ang:=2*Pi/numver;
read(zentr.x,zentr.y,pp.x,pp.y);
mnog[i].v[1]:=pp;
inc(n);
ver[n]:=pp;
for j:=2 to numver do
begin
next.x:=(pp.x-zentr.x)*cos(ang)-(pp.y-zentr.y)*sin(ang)+zentr.x;
next.y:=(pp.y-zentr.y)*cos(ang)+(pp.x-zentr.x)*sin(ang)+zentr.y;
pp:=next;
inc(n);
ver[n]:=pp;
mnog[i].v[j]:=pp;
end;
mnog[i].v[numver+1]:=mnog[i].v[1];
end;
inc(n);
ver[n]:=stver;
inc(n);
ver[n]:=endver;
k:=0;
inc(numlake);
mnog[numlake].n:=1;
mnog[numlake].v[1]:=stver;
mnog[numlake].v[2]:=stver;
inc(numlake);
mnog[numlake].n:=1;
mnog[numlake].v[1]:=endver;
mnog[numlake].v[2]:=endver;
for i:=1 to numlake do
begin
for j:=k+1 to k+mnog[i].n-1 do
begin
a[j,j+1]:=sqrt(sqr(ver[j].x-ver[j+1].x)+sqr(ver[j].y-ver[j+1].y));
a[j+1,j]:=a[j,j+1];
end;
a[mnog[i].n+k,1+k]:=sqrt(sqr(ver[mnog[i].n+k].x-ver[1+k].x)+sqr(ver[mnog[i].n+k].y-ver[1+k].y));
a[1+k,mnog[i].n+k]:=a[mnog[i].n+k,1+k];
inc(k,mnog[i].n);
end;
k:=0;
for i:=1 to numlake do
begin
for j:=k+1 to k+mnog[i].n do
for l:=k+mnog[i].n+1 to n do
begin
flag:=true;
x:=1;
{s:=0;}
if (abs(ver[l].x-ver[j].x)<delta)and(abs(ver[l].y-ver[j].y)<delta) then x:=numlake+1;
while (x<=numlake)and flag do
begin
y:=1;
while (y<=mnog[x].n)and flag do {if (s+y<>j)and(s+y<>l)and(s+y mod mnog[x].n+1<>j)and(s+y mod mnog[x].n+1<>l) then}
begin
numzero:=0;
v1.x:=ver[l].x-ver[j].x;
v1.y:=ver[l].y-ver[j].y;
v2.x:=mnog[x].v[y].x-ver[j].x;
v2.y:=mnog[x].v[y].y-ver[j].y;
v3.x:=mnog[x].v[y+1].x-ver[j].x;
v3.y:=mnog[x].v[y+1].y-ver[j].y;
sign1:=sign(v1.x*v2.y-v1.y*v2.x);
sign2:=sign(v1.x*v3.y-v1.y*v3.x);
inc(numzero,2-abs(sign1)-abs(sign2));
if sign1<>sign2 then p1:=true else p1:=false;
v1.x:=mnog[x].v[y+1].x-mnog[x].v[y].x;
v1.y:=mnog[x].v[y+1].y-mnog[x].v[y].y;
v2.x:=ver[j].x-mnog[x].v[y].x;
v2.y:=ver[j].y-mnog[x].v[y].y;
v3.x:=ver[l].x-mnog[x].v[y].x;
v3.y:=ver[l].y-mnog[x].v[y].y;
sign1:=sign(v1.x*v2.y-v1.y*v2.x);
sign2:=sign(v1.x*v3.y-v1.y*v3.x);
inc(numzero,2-abs(sign1)-abs(sign2));
if sign1<>sign2 then p2:=true else p2:=false;
if (p1 and p2)and(numzero<2) then flag:=false;
inc(y);
end;{ else inc(y);}
{inc(s,mnog[x].n);}
inc(x);
end;
if flag then
begin
a[j,l]:=sqrt(sqr(ver[l].x-ver[j].x)+sqr(ver[l].y-ver[j].y));
a[l,j]:=a[j,l];
end;
end;
inc(k,mnog[i].n);
end;
fillchar(q,sizeof(q),0);
for i:=1 to n do f[i]:=nv;
q[n-1]:=1;
f[n-1]:=0;
flag:=true;
while flag do
begin
min:=0;
flag:=false;
for i:=1 to n do if (q[i]=1)and((min=0)or(f[i]<f[min]))then
begin
flag:=true;
min:=i;
end;
if min<>0 then q[min]:=2;
if flag then
for i:=1 to n do if a[min,i]+f[min]<f[i] then
begin
q[i]:=1;
f[i]:=a[min,i]+f[min];
end;
end;
writeln(f[n]);
end.message:
{$APPTYPE CONSOLE}
{$B-,R-,H+}
const
maxl=10000;
base=257;
modul=299993;
type
tlist=record
pol:smallint;
next:longint;
end;
var
s1,s2,s:string;
len1,len2:smallint;
hash:array[1..modul] of record
first,last:smallint;
end;
h:smallint;
table:array[1..maxl] of tlist;
function CheckStr(i,j,k:smallint):boolean;
var
l:smallint;
begin
l:=0;
while (l<k)and(s1[i+l]=s2[j+l])do inc(l);
if l=k then CheckStr:=true else CheckStr:=false;
end;
function CheckSeq(k:smallint):boolean;
var
i:smallint;
tekhash,maxdigpow:longint;
teklist:smallint;
begin
fillchar(hash,sizeof(hash),0);
h:=0;
tekhash:=0;
maxdigpow:=1;
for i:=1 to len1 do
begin
tekhash:=(base*tekhash+Ord(s1[i])) mod modul;
if i<=k then maxdigpow:=(maxdigpow*base) mod modul else
tekhash:=(tekhash+modul-(maxdigpow*Ord(s1[i-k]))mod modul)mod modul;
if i>=k then
begin
if hash[tekhash].first<>0 then
begin
teklist:=hash[tekhash].last;
inc(h);
table[teklist].next:=h;
teklist:=table[teklist].next;
table[teklist].pol:=i-k+1;
table[teklist].next:=0;
hash[tekhash].last:=teklist;
end else
begin
inc(h);
hash[tekhash].first:=h;
teklist:=hash[tekhash].first;
table[teklist].pol:=i-k+1;
table[teklist].next:=0;
hash[tekhash].last:=teklist;
end;
end;
end;
tekhash:=0;
maxdigpow:=1;
for i:=1 to len2 do
begin
tekhash:=(base*tekhash+Ord(s2[i])) mod modul;
if i<=k then maxdigpow:=(maxdigpow*base) mod modul else
tekhash:=(tekhash+modul-(maxdigpow*Ord(s2[i-k]))mod modul)mod modul;
if (i>=k)and(hash[tekhash].first<>0)then
begin
teklist:=hash[tekhash].first;
repeat
if CheckStr(table[teklist].pol,i-k+1,k) then
begin
CheckSeq:=true;
exit;
end;
teklist:=table[teklist].next;
until teklist=0;
end;
end;
CheckSeq:=false;
end;
function GetMaxSubseqLength:smallint;
var
l,r,tek:smallint;
begin
l:=1;
r:=len1;
if not CheckSeq(l) then
begin
GetMaxSubseqLength:=0;
exit;
end;
if CheckSeq(r) then
begin
GetMaxSubseqLength:=r;
exit;
end;
while l<>r do
begin
tek:=(l+r) div 2+1;
if CheckSeq(tek) then l:=tek else r:=tek-1;
end;
GetMaxSubseqLength:=l;
end;
begin
readln(s1);
readln(s2);
if length(s1)>length(s2) then
begin
s:=s1;
s1:=s2;
s2:=s;
end;
len1:=length(s1);
len2:=length(s2);
writeln(GetMaxSubseqLength);
end.Відредаговано partisan (2006-01-20 18:13:35)
Поза форумом
xXx написав:
Не совсем, если K=1, то задача сводиться к задаче о нахождении числа инверсий в массиве, все елементы которого разлиичные натуральные числа, не превосходящие N... В своём решении я использовал именно этот факт...
Расскажи пожайлуста свое решение, с оценкой сложности алгоритма
И еще... В GNU printf("I64d", R) - выводит, почему-то, не то, что надо. Напиши cout << R и пройдешь все тесты!
Відредаговано Victor Barinov (2006-01-21 00:37:05)
Поза форумом
Victor Barinov написав:
xXx написав:
Не совсем, если K=1, то задача сводиться к задаче о нахождении числа инверсий в массиве, все елементы которого разлиичные натуральные числа, не превосходящие N... В своём решении я использовал именно этот факт...
Расскажи пожайлуста свое решение, с оценкой сложности алгоритма
И еще... В GNU printf("I64d", R) - выводит, почему-то, не то, что надо. Напиши cout << R и пройдешь все тесты!
Если быть точным, то сложность - O(K*rN^2+(N-rN)*(rN+O(GetIndex)*min(abs(Ai-Aj)))), где rN - произвольная натуральная константа...(я использовал 13), O(GetIndex) - сложность получения индекса елемента по значению(1), i = rN, rN+1, ... , N-1, j = i-rN, i-rN+1, ... , i-1...
Также сложность можно представить как O(N*rN*dA)) dA ~ не помню как считать
, но если сгенерить массив случайных, натуральных, различных, не превосходящих N чисел, то dA ~ Summa(g(i))/N, g(i)=min(abs(A[i]-A[j]), j-i>0 and j-i<=rN...
теоретически на самом плохом тесте можно добиться сложности O(N^2)... (dA = N/rN)
По памяти - O(N)
Алгоритм:
Предположим у нас есть функция f(i,k,min), которая даёт решение для элементов, индекс которых не меньше i, значения не меньше min, тогда f(1,K,1) - решение задачи...
f(i,k,min) = f(i+1,k-1,A[i])+f(i+1,k,min)
итерируя, можно получить формулу
f(i,k,min) = f(i+1,k-1,A[i])+f(i+2,k-1,A[i+1])+f(i+3,k-1,A[i+2])+...
Предоложим мы нашли f(j,k,1), f(i+1,k-1,1), f(i+2,k-1,1), ... , j>i,
тогда f(i,k,1)=f(i+1,k-1,A[i]+...+f(j,k-1,A[i])+f(j,k,1)+sgn(A[i]-A[j])*f(j,k,A[i])
найти f(j,k,A[i]) можно за O(abs(A[i]-A[j])*O(GetIndex)) перебирая индексы элементов, и если индекс превосходит j, то добавляем решение для этого елемента при k-1 к уже найденному решению f(j,k,A[i]).Получить индекс мы можем за O(1), для этого следует хранить индексы элементов в отельном массиве...
----------------------
Не знаю как можно это решение объяснить понятно...![]()
Идея тут одна - использовать дополнительный массив индексов, по которому можно быстро определить sgn((A[i]-A[j])*(i-j)), для любого A[i],A[j],i,j...
Відредаговано xXx (2006-01-23 14:40:13)
Поза форумом
Лучше б ты просто прокомментировал свою прогу.
Хотя, учитывая твой стиль программирования, боюсь, здесь и это бесполезно. ![]()
Поза форумом
ROBOT написав:
Тесты: http://www.proveryalka.narod.ru/tests.html
Решения на Паскале: http://www.h0h0l.narod.ru
Временная сложность моих решений:
NewDomino - O(50K)
DSP2 - O(N^3)
Army - не решил
Lake - не решил
Message - O(Length(S1)*Length(S2)) - тупо, но лучше не придумал...
У кого решения лучше - пишите сюда.
Если придумали тесты - тоже пишите (все тесты, которые будут здесь написаны, я добавлю на свой сайт)
а мои решения на www.sosiska.ru!
Поза форумом