Removing Stones (2019 Nian cattle off more school third partition of G + heuristic)

Topic Link

Portal

The meaning of problems

When the initial \ (n-\) stack stones, stones per number of stones piled \ (a_i \) , then the game.

Rules of the game you can choose any two piles of stones, then removed a heap of stones from these two, and finally the number of stones becomes \ (0 \) is the winner otherwise fails. Since the total number of stones may be odd, not win this time, and therefore added a rule if the number is odd stone, you can advance to remove a stone.

I ask you how many intervals to make people play the game to win.

Thinking

After a model transformation that Italy becomes the number of intervals, the interval and the number of stones greater than equal to twice the maximum number of stones.

Heuristic divide and conquer, and the general approach that question the same.

Code

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson (rt<<1),L,mid
#define rson (rt<<1|1),mid + 1,R
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 300000 + 2;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

LL ans;
int _, n;
LL sum[maxn];
int a[maxn], dp[maxn][20], pos[maxn][20], lg[maxn];

void init() {
    lg[0] = -1;
    for(int i = 1; i <= n; ++i) lg[i] = lg[i>>1] + 1;
    for(int j = 1; j <= lg[n]; ++j) {
        for(int i = 1; i + (1<<j) - 1 <= n; ++i) {
            if(dp[i][j-1] >= dp[i+(1<<(j-1))][j-1]) {
                dp[i][j] = dp[i][j-1];
                pos[i][j] = pos[i][j-1];
            } else {
                dp[i][j] = dp[i+(1<<(j-1))][j-1];
                pos[i][j] = pos[i+(1<<(j-1))][j-1];
            }
        }
    }
}

int query(int l, int r) {
    int k = lg[r-l+1];
    if(dp[l][k] >= dp[r-(1<<k)+1][k]) return pos[l][k];
    else return pos[r-(1<<k)+1][k];
}

void solve(int l, int r) {
    if(l >= r) return;
    if(l + 1 == r) {
        ans += (a[l] == a[r]);
        return;
    }
    int pos = query(l, r);
    if(r - pos > pos - l) {
        for(int i = l; i <= pos; ++i) {
            int ub = r, lb = pos + 1, mid, pp = -1;
            if(i != pos) lb = pos;
            while(ub >= lb) {
                mid = (ub + lb) >> 1;
                if(sum[mid] - sum[i-1] >= 2 * a[pos]) {
                    pp = mid;
                    ub = mid - 1;
                } else {
                    lb = mid + 1;
                }
            }
            if(pp == -1) continue;
            ans += (r - pp + 1);
        }
    } else {
        for(int i = pos; i <= r; ++i) {
            int ub = pos - 1, lb = l, mid, pp = -1;
            if(i != pos) ub = pos;
            while(ub >= lb) {
                mid = (ub + lb) >> 1;
                if(sum[i] - sum[mid-1] >= 2 * a[pos]) {
                    pp = mid;
                    lb = mid + 1;
                } else {
                    ub = mid - 1;
                }
            }
            if(pp == -1) continue;
            ans += (pp - l + 1);
        }
    }
    solve(l, pos - 1), solve(pos + 1, r);
}

int main() {
#ifndef ONLINE_JUDGE
    FIN;
#endif
    scanf("%d", &_);
    while(_--) {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            sum[i] = sum[i-1] + a[i];
            dp[i][0] = a[i];
            pos[i][0] = i;
        }
        init();
        ans = 0;
        solve(1, n);
        printf("%lld\n", ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Dillonh/p/11391423.html