Сначала считаем функцию Гранди для каждой из n цепочек(функция calc(num,l,r) считает функцию Гранди в цепочке номер num на интервале [l;r]). Потом считаем xor этих функций. Если он ненулевой, то перебираем все возможные варианты первого хода(функция good), иначе говорим, что выигрывает второй игрок.
2 2012-04-16 22:24:26
Тема: Timus 1540 (2 ответов, оставленных в Problems)
Разбирал статью про теорему Шпрага-Гранди, но на эту задачу всё время выдает WA. Подскажите кто-нибудь, что у меня тут неправильно. Код: http://pastebin.com/m5vGBMvF Задача: acm.timus.ru/problem.aspx?space=1&num=1540
3 2012-04-16 21:59:15
Re: помогите решить ету задачу (3 ответов, оставленных в Problems)
Это же белорусская респа 2011, если я правильно понял.
Тогда сначала посчитаем для каждой клетки ДП:
r[ i ][j] - ближайшее справа дерево, l[ i ][j] - ближайшее слева дерево, u[ i ][j] - ближайшее сверху дерево, d[ i ][j] - ближайшее снизу дерево. Теперь f[ i ][j]=min(u[ i ][j],l[ i ][j]) - (неформально) насколько ячейка может быть правой нижней у квадрата, g[ i ][j]=min(r[ i ][j],d[ i ][j]) - насколько ячейка может быть левой верхней у квадрата. Посчитали все это за O(N^2) и теперь смотрим нашу матрицу подиагонально, ставим и убираем единички в сумматоре с учетом f и g, и получаем решение за O(N^2*logN). http://pastebin.com/8mbbMtEH - мой код, правда он очень старый и малочитаемый.
4 2011-04-27 12:06:47
Re: Дерево Фенвика (3 ответов, оставленных в Feedback)
#include <iostream>
#include <cstdio>
#include <memory.h>
#define maxn 10000
#define inf 1000000000
using namespace std;
int m[maxn],n,l[maxn],r[maxn];
int prev(int x)
{
return (x&(x-1));
}
int next(int x)
{
return ((x<<1)-prev(x));
}
void modify(int pos, int value)
{
int p;
for (p=pos;p<=n;p=next(p)) r[p]=max(r[p],value);
m[pos]=max(m[pos],value);
for (p=pos;p>0;p=prev(p)) l[p]=max(l[p],value);
}
int findmax(int ll,int rr)
{
int res,p;
res=-inf;
for (p=ll;next(p)<=rr;p=next(p)) res=max(res,l[p]);
res=max(res,m[p]);
for (p=rr;prev(p)>=ll;p=prev(p)) res=max(res,r[p]);
return res;
}
void init(void)
{
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
cin>>n;
int x,i;
for (i=1;i<=n;i++)
m[i]=r[i]=l[i]=-inf;
for (i=1;i<=n;i++)
{
cin>>x;
modify(i,x);
}
}
void sol(void)
{
int i,j;
for (i=1;i<=n;i++,cout<<endl)
for (j=i;j<=n;j++)
cout<<findmax(i,j)<<" ";
}
int main(void)
{
init();
sol();
cin>>n;
return 0;
}
Тут сама реализация и за одно вводит массив на N элементов и выводит максимумы для всех возможных L и R. Самый большой минус - элементы можно только увеличивать, но это компенсируется большей скоростью работы, чем RMQ, и простотой написания. Дерево Фенвика для нахождения максимумов на интервале называется "максимизатор", для минимумов - "минимизатор"(в частности для максимумов на интервале [0;R] - "максиматор", для сумм - "сумматор"). А вообще на двумерную матрицу эта штука довольно трудно пишется.
5 2011-04-26 09:04:12
Тема: Дерево Фенвика (3 ответов, оставленных в Feedback)
Написано, что находит максимум/минимум только на отрезке [0;R]. У меня есть реализация, которая ищет на отрезке [L;R], могу скинуть или сам ее знаешь Короче статью стоит подправить