1

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

Несложно представить n^2+n+x в виде
A(n+y)^2 + B(n+y) + C где A, B, C - не зависят от n.
тогда мы получаем что у нас есть констана (от x и y)
и мы ее считаем по модулю n+y
Т.к. x и y небольшие, то понятно что при больших n модуль
станет больше константы и дальше считать нет смысла.
Итого: находим верхнюю границу для n (она не большая) и
считаем только до нее.

2

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

250: там есть строчеа в условии про то что кусок из треугольников связный, т.е. такой тест неверный

500:
сколько нечетных чисел не больше N?
(N+1)/2
чему равно сумма первых K нечетных чисел? K*K
выкинем все нечетные что осталось?
N/2 четных от 2, 4, ...
если мы каждое из них разделим на 2, то во-первых ответ не изменится,
а во вторых мы получим изначальную задачу только в два раза меньшего размера

3

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

в 250 поверните мысленно картинку на 45 градусов против часовой стрелки.
тогда весь путь будет состоять из горизонтальных и вертикальных отрезков, причем только вверх в вправо.
понятно, что длина такого пути определяетя однозначно изходя из начальной и конечной точек.

в 500 я не понял зачем нужна рекурсия, ведь и без нее решения очевидное:

long long findSum( long long N ) {
    long long res=0;
    while (N){
        res += ((N+1)/2)*((N+1)/2);
        N /= 2;
    }
    return res;
}

4

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

Обычный алгоритм с dfs нормально проходит...

#include <cstdio>
#include <vector>

using namespace std;

#define Size(x) (int)(x).size()
#define For(i,a,b) for(int i=(int)(a);i<=(int)(b);++i)
#define RepV(i,v) for (int i=0;i<Size(v);++i)
#define Fill(a,b) memset(&a,b,sizeof(a))

int n, m, v[1005], xy[1005], yx[1005];
vector<int> x[1005];

int go(int u){
    if ( v[u]++ ) return 0;
    
    RepV(i, x[u]) if ( !yx[x[u][i]] || go( yx[x[u][i]] ) ) {
        xy[u] = x[u][i];
        yx[x[u][i]] = u;
        return 1;
    }
    
    return 0;
}

int main(){
    int k;
    scanf("%d%d%d", &n, &m, &k);
    
    For(i, 1, k) {
        int a, b;
        scanf("%d%d", &a, &b);
        x[a].push_back(b);
    }
    
    int max_bipartite_matching = 0;
    For(i, 1, n) if ( !xy[i] ) {
        Fill(v, 0);
        max_bipartite_matching += go(i);
    }
    
    printf("%d", n + m - max_bipartite_matching );
    
    return 0;
}

5

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

Они являются соседними. На k-той итерации есть несколько "корзин". В каждой из них находятся суффиксы у которых первые k символов совпадают. Под соседством имеется ввиду соседство корзин. С каждой итерацией происходит уточнение этих корзин с учетом 2^k символов. Если две корзины соседние, то есть два варианта. Либо на предыдущей итерации они были одной корзиной и в результате уточнения распались, тогда у них суффиксов этих корзин первые половинки совпадают. Либо на предыдущей итерации они уже были разными корзинами, тогда эти разные корзины обязательно были соседними, потому что если бы это было не так, то на текущей итерации наши уточненные корзины уж тем более не были бы соседними...

6

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

Числа в нижней строке имеют вид n*(n+1)/2
т.е мы за O(sqrt(n)) можем найти диагональ, ну а потом уже и все остальное за O(1)

7

(7 ответов, оставленных в Algo)

Суть в том, что часто задача для вершины естественным образом сводится к задаче для связанных вершин, а так как в дереве нет циклов, то применима динамика. Динамику обычно запускают из одной вершины, тем самым представляя дерево подвешенным за эту вершину (корень). Тогда у каждой вершины, кроме корня, будет ровно один родитель и несколько детей.

8

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

Я решал так:
При маленьких k величина n/k-n/(k+1) довольно большая. При k близких к корню от n она начинает приближаться к единице. Найдем первое место где n/k-n/(k+1)==1. Затем оно будет и дальше убывать на 1 пока наконец не станет нулем. Соответственно бин. поиском ищем это место.

long long solve(long long n){
    int sq = sqrt((double)n);
    long long st = n/sq;

    long long l = sq, r = sq + 100000000;
    if (n/l == n/(l+1)) return l;
    while (n/l-n/(l+1) > 1) ++l;
    if (n/l == n/(l+1)) return l;
    st = n/l;
    sq=l;

    while (l+1<r){
        long long m = (l+r)/2;
        long long srx = n/m;
        if (st-srx == m - sq) l=m; else r=m;
    }

    return l;
}

9

(15 ответов, оставленных в Algo)

vectror<bool> сокращает память не в 4, а в 32 раза, потому что внутренне он реализован так, чтобы хранить информацию в битах, а не байтах.

10

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

За NlogN можно без всяких деревьев, встроенными в C++ структурами.
Путь каждая точка конца отрезка это состояние. Будем там хранить начало это или конец, цвет и уровень.
Уровень это порядок в котором отрезки кладутся. Виден отрезок с наибольшим уровнем.
Тогда перебирая все точки в порядке возрастания будем поддерживать set<уровней> из которого будем делать выводы какой отрезок виден.

Код:

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <set> 

using namespace std;

#define Size(x) (int)(x).size()
#define For(i,a,b) for(int i=(int)(a);i<=(int)(b);++i)
#define RepV(i,v) for (int i=0;i<Size(v);++i)

struct state{
    int x, level;
    char start, color;
    state(int x, int level, char start, char color):x(x),level(level),start(start),color(color){}
};

bool by_x(state& a, state& b){
    if (a.x!=b.x) return a.x < b.x;
    if (a.start != b.start) return a.start < b.start;
    return a.level < b.level;
}

int main(){
    vector<state> states;
    states.push_back(state(0,0,1,'w'));
    states.push_back(state(1000000000,0,0,'w'));
    int n;
    scanf("%d",&n);
    For(i,1,n){
        int a, b;
        char c;
        scanf("%d%d %c\n",&a,&b,&c);
        states.push_back(state(a,i,1,c));
        states.push_back(state(b,i,0,c));
    }

    sort(states.begin(),states.end(),by_x);

    vector<pair<int,int> >wlist;
    set<int> w, b;
    RepV(i,states){
        state cur = states[i];
        char color='b';
        if (Size(b)==0 || ( Size(w)>0 && *b.rbegin() < *w.rbegin())){
            color='w';
        }
        if (color=='w'){
            if (i>0)
                wlist.push_back(make_pair(states[i-1].x,cur.x));
        }
        if (!cur.start)
            if (cur.color=='w') w.erase(w.find(cur.level));
            else b.erase(b.find(cur.level));
        else
            if (cur.color=='w') w.insert(cur.level);
            else b.insert(cur.level);
    }

    int len = 0, left = 0;

    int l=-1,r=-1;
    RepV(i,wlist){
        if (wlist[i].first == r) {
            r = wlist[i].second;
        } else {
            if (r-l > len){
                len = r-l;
                left=l;
            }
            l=wlist[i].first;
            r=wlist[i].second;
        }
    }

    if (r-l > len){
        len = r-l;
        left=l;
    }
    printf("%d %d",left,left + len);

    return 0;
}

11

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

возьмите все концы всех отрезков и отсортируйте. эти точки разделят отрезок (0,10^9) на какое-то кол-во отрезков. чтобы найти цвет отрезка просто берете его середину и перебирая все перекрашивания находите. итого все это будет работать за O(N^2).

12

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

e-maxx пишет:

Alexey
Точно smile Пусть первая вершина в (0;0), вторая - в (x;y), тогда третья должна получаться поворотом вектора (x;y) на 60 градусов, и в результате неизбежно появится sqrt(3).

Задача: доказать что при всех N кроме 4 правильных N-угольников с целыми вершинами не существует.
Не программистская, но довольно интересная...

13

(1 ответов, оставленных в Algo)

http://en.wikipedia.org/wiki/Hopcroft%E … _algorithm

14

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

http://rain.ifmo.ru/cat/data/theory/gra … rticle.pdf