1

(2 ответов, оставленных в Problems)

Сначала считаем функцию Гранди для каждой из n цепочек(функция calc(num,l,r) считает функцию Гранди в цепочке номер num на интервале [l;r]). Потом считаем xor этих функций. Если он ненулевой, то перебираем все возможные варианты первого хода(функция good), иначе говорим, что выигрывает второй игрок.

2

(2 ответов, оставленных в Problems)

Разбирал статью про теорему Шпрага-Гранди, но на эту задачу всё время выдает WA. Подскажите кто-нибудь, что у меня тут неправильно. Код: http://pastebin.com/m5vGBMvF Задача: acm.timus.ru/problem.aspx?space=1&num=1540

3

(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

(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

(3 ответов, оставленных в Feedback)

Написано, что находит максимум/минимум только на отрезке  [0;R]. У меня есть реализация, которая ищет на отрезке [L;R], могу скинуть или сам ее знаешь smile Короче статью стоит подправить