Summer N Tianle [articles] game --2019 cattle off summer school and more training camp (third)

This relatively speaking, a little friendship, had to make up a few days ago about it, and then forget to send a ...

Solutions include the following problem: \ (A \ \ \ B \ \ \ F. \ \ \ G \ \ \ H \ \ \ J \)

\ (D \) questions his teammates up, and I do not bother to think mathematical formula problem, so the solution of the venue and other issues.

Contest Address: https://ac.nowcoder.com/acm/contest/883#question

[A] Graph Games randomized block +

Given \ (n-\) points and \ (m \) edges define \ (S (x) \) is and (X \) \ for all points of a set of adjacent points. For \ (Q \) operations, divided into two types:

  • Flip \ ([l, r] \ ) state inside the interval, there is -> Delete edge, there is no -> bordered
  • Ask \ (S (u) \) is equal to \ (S (v) \)

Wherein \ (n-\ Leq 1E. 5 ^ \ \ m \ Leq 2E. 5 ^ \ \ Q \ Leq 2E. 5 ^ \) .

As the need to meet the same set of contiguous whole, if each check point, this complexity has been blown up. Thus each point considered to assign a random number , using a different random number determines whether the same set or can be shown (probably) does not occur in case of conflict.

Because of the huge range and requires the use of block operations to reduce complexity in the block for the update can be directly updated; interblock for update, then the need to use \ (the lazy \) labeled with \ (lazy == 1 \) represents the current block need to be considered. \ (SUM \) weight value of each point to be updated in each memory array, \ (S \) arrays are stored for each single-point values can be updated.

Recommendations with the code to understand.

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

const int maxn = 2e5+5;
const int sqrtn = 5e2+5;

int n, m;
int num;
int block;
int u[maxn];
int v[maxn];
int val[maxn];      // 随机权值(大概可以保证异或值不发生冲突【重复】)
int belong[maxn];
int l[sqrtn];
int r[sqrtn];
int lazy[sqrtn];    // 整块翻转标记
ll s[maxn];         // 每个点的异或值
ll sum[sqrtn][maxn];// 每块里每个点待更新的权值

void build() {      // 分块建立
    block = sqrt(m);
    num = m / block;
    if(m % block != 0) {
        num ++;
    }
    for(int i = 1; i <= num; i++) {
        l[i] = (i-1)*block + 1;
        r[i] = i*block;
        lazy[i] = 1;    // 初始赋值 1 代表当前块可以使用
        for(int j = 1; j <= n; j++) {
            sum[i][j] = 0;
        }
    }
    r[num] = m;
    for(int i = 1; i <= m; i++) {
        belong[i] = (i-1)/block+1;
    }
    for(int i = 1; i <= n; i++) {
        s[i] = 0;
    }
}

void update(int l, int r) {     // 分块更新
    if(belong[l] == belong[r]) {
        for(int i = l; i <= r; i++) {
            s[u[i]] ^= val[v[i]];
            s[v[i]] ^= val[u[i]];
        }
        return ;
    }
    for(int i = l; belong[i] == belong[l]; i++) {
        s[u[i]] ^= val[v[i]];
        s[v[i]] ^= val[u[i]];
    }
    for(int i = r; belong[i] == belong[r]; i--) {
        s[u[i]] ^= val[v[i]];
        s[v[i]] ^= val[u[i]];
    }
    for(int i = belong[l]+1; i < belong[r]; i++) {
        lazy[i] ^= 1;   // 翻转
    }
}

int main() {
    srand(time(NULL));
    for(int i = 0; i < maxn; i++) {
        // 每个点赋予随机权值,加点删点都是异或操作
        val[i] = rand() + 1;
    }
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        build();    // 按 m 分块
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &u[i], &v[i]);
            sum[belong[i]][u[i]] ^= val[v[i]];
            sum[belong[i]][v[i]] ^= val[u[i]];
        }
        int q;
        scanf("%d", &q);
        for(int i = 1; i <= q; i++) {
            int f, x, y;
            scanf("%d%d%d", &f, &x, &y);
            if(f == 1) {
                update(x, y);
            }
            else {
                ll ans1 = s[x];     // 单点的情况
                ll ans2 = s[y];
                for(int i = 1; i <= num; i++) { // 整块的情况
                    if(lazy[i]) {
                        ans1 ^= sum[i][x];
                        ans2 ^= sum[i][y];
                    }
                }
                if(ans1 == ans2) {
                    printf("1");
                }
                else {
                    printf("0");
                }
            }
        }
        printf("\n");
    }
    return 0;
}

[B] Crazy Binary String greedy

Given a \ (01 \) string, were selected and one of the longest substring sequences, which make \ (0 \) and \ (1 \) the same number.

It is obvious that for the sequence interval \ (min (sum_1, sum_0) \) ;

For the substring is need to maintain the prefix and then find the location of the same value as the first occurrence.

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

const int maxn = 1e5+5;

char s[maxn];

map<int, int> mp;

int main() {
    int n;
    while(~scanf("%d", &n)) {
        scanf("%s", s+1);
        int a = 0, b;
        mp.clear();

        int x = 0, y = 0;

        int cnt = 0;
        for(int i = 1; i <= n; i++) {
            if(s[i] == '0') {
                x ++;
                cnt --;
                if(cnt == 0) {
                    a = max(a, i);
                    continue;
                }
                if(mp[cnt] == 0) {
                    mp[cnt] = i;
                    continue;
                }
                a = max(a, i-mp[cnt]);
                
            }
            else {
                y ++;
                cnt ++;
                if(cnt == 0) {
                    a = max(a, i);
                    continue;
                }
                if(mp[cnt] == 0) {
                    mp[cnt] = i;
                    continue;
                }
                a = max(a, i-mp[cnt]);               
                
            }
        }
        b = min(x, y) * 2;
        printf("%d %d\n", a, b);
    }
    return 0;
}

[F] Planting Trees queue monotone

Given a \ (n * n \) weight matrix of each point and the value \ (A_ ij of {} \) , to find a largest rectangle, such that the difference between maximum and minimum of the internal weights of not more than rectangular \ (m \) .

Monotonous need to define two queues, to maintain a current maximum, minimum maintenance another, then ... say it is too complicated, the code look like. In addition \ (deque \) directly if I was TLE, so handwriting.

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
 
const int maxn = 5e2+5;
 
int cmax[maxn], cmin[maxn];     // 列最大最小值
int qmax[maxn*2], qmin[maxn*2]; // 单调队列(双端)
int a[maxn][maxn];
int l1, r1, l2, r2;
int ans, n, m;
 
int solve() {
    l1 = l2 = 0;
    r1 = r2 = 0;
    int x = 1;
    int temp = 0;
    memset(qmin, 0, sizeof(qmin));
    memset(qmax, 0, sizeof(qmax));
    for(int i = 1; i <= n; i++) {
        while(l1 < r1 && cmax[qmax[r1-1]] < cmax[i]) {
            r1--;
        }
        qmax[r1++] = i;
        while(l2 < r2 && cmin[qmin[r2-1]] > cmin[i]) {
            r2--;
        }
        qmin[r2++] = i;
        while(l1 < r1 && l2 < r2 && cmax[qmax[l1]] - cmin[qmin[l2]] > m && x <= i) {
            x = min(qmax[l1], qmin[l2])+1;
            if(qmax[l1] < qmin[l2]) {
                l1++;
            }
            else if(qmax[l1] > qmin[l2]) {
                l2++;
            }
            else {
                l1++;
                l2++;
            }
        }
        temp = max(temp, i-x+1);
    }
    return temp;
}
 
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        ans = 0;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= n; j++) {
                scanf("%d", &a[i][j]);
            }
        }
        for(int i = 1; i <= n; i++) {
            for(int k = 1; k <= n; k++) {
                cmax[k] = 0;
                cmin[k] = inf;
            }
            for(int j = i; j <= n; j++) {
                for(int k = 1; k <= n; k++) {
                    cmax[k] = max(cmax[k], a[j][k]);
                    cmin[k] = min(cmin[k], a[j][k]);
                }
                ans = max(ans, solve()*(j-i+1));
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

【G】 Removing Stones RMQ+二分

Given \ (n-\) stack stones, each non-empty piles can select a respective stone removal, if the last light can take it can win. Q. How many sections exist \ ([L, r] \) , meet the definition of win space. Further, if the total number of stones within the interval is odd, then the minimum number of first remove a pile of stones.

Win game conditions: the total number of stone sections and \ (SUM \) > = twice the interval maximum value \ (max \) .
So the first use of \ (RMQ \) jurisdictional boundaries on the range you can find the best value, then the contribution of the interval are counted with the largest number in the pile of stones in the interval, before processing a stone \ ([l, r] \) , and then enumerate the side, half looking for the other side.

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

const int maxn = 300000+5;

int dp_max[maxn][25];   // 维护区间最大值
int pos[maxn][25];      // 维护区间最大值的位置
int a[maxn];
int n;
ll sum_f[maxn];         // 前缀和
ll sum_b[maxn];         // 后缀和

void RMQ() {
    for(int i = 1; i <= n; i++) {
        dp_max[i][0] = a[i];
        pos[i][0] = i;
    }
    for(int j = 1; (1<<j) <= n; j++) {
        for(int i = 1; i+(1<<j)-1 <= n; i++) {
            if(dp_max[i][j-1] >= dp_max[i+(1<<(j-1))][j-1]) {
                dp_max[i][j] = dp_max[i][j-1];
                pos[i][j] = pos[i][j-1];
            }
            else {
                dp_max[i][j] = dp_max[i+(1<<(j-1))][j-1];
                pos[i][j] = pos[i+(1<<(j-1))][j-1];
            }

        }
    }
}

int query_pos(int l, int r) {   // 查询区间最值所在位置
    int k = log2(r-l+1);
    if(dp_max[l][k] >= dp_max[r-(1<<k)+1][k]) {
        return pos[l][k];
    }
    return pos[r-(1<<k)+1][k];
}

ll solve(int l, int r) {
    if(l >= r) {
        return 0;
    }
    int p = query_pos(l, r);    // 区间最值位置
    // printf("l == %d  r == %d  p == %d\n", l, r, p);
    ll ans = 0;
    if(p-l < r-p) {     // 更靠近左端点
        for(int i = l; i <= p; i++) {
            ans += (r - (lower_bound(sum_f+p, sum_f+r+1, sum_f[i-1]+2*a[p])-(sum_f+1)));
            // 区间和必须 >= 二倍区间最大值【条件x】
            // 对答案的贡献 == (右端点位置 - 满足条件的最左端【满足条件x】)
        }
    }
    else {
        for(int i = p; i <= r; i++) {
            ans += ((n-l+1) - (lower_bound(sum_b+(n-p+1), sum_b+(n-l+1)+1, sum_b[n-i]+2*a[p])-(sum_b+1)));
            // 后缀是反着存的,所以处理时也是反着
        }
    }
    return ans + solve(l, p-1) + solve(p+1, r);
}

int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        sum_f[0] = sum_b[0] = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            sum_f[i] = sum_f[i-1] + a[i];
        }
        for(int i = 1; i <= n; i++) {
            sum_b[i] = sum_b[i-1] + a[n-i+1];
        }
        RMQ();
        printf("%lld\n", solve(1, n));
    }
    return 0;
}

[H] Magic Line mathematics

Given the two-dimensional plane \ (n \) (even-numbered) points, these need to draw a straight line n points equally divided into two, the output of any two coordinates (integer) on the straight line.

Is a solution to a problem will be able to direct two keywords sorted AC, the game is still a little time to think too much, my solution is to first find a point in the third quadrant [] from quite far away, then this point is " \ ( P \) point "polar angle for sorting, and sorting is taken" mid-point "and the point \ (P \) point to take the other end of the connection, then the abscissa -1 to (and does not guarantee the" midpoint "intersect ).

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
 
const int maxn = 1e5+5;
 
struct node {
    ll x, y;   
}p[maxn];
 
ll jud(node p1, node p2, node p0) {
    ll ans = (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
    return ans;
}
 
bool cmp(node a, node b) {
    ll c = jud(node{-100000000, -10000}, b, a);
    return c < 0;
}
 
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%lld%lld", &p[i].x, &p[i].y);
        }
        sort(p+1, p+1+n, cmp);
        ll x = p[n/2].x;
        ll y = p[n/2].y;
        ll xx = 2*x + 100000000;
        ll yy = 2*y + 10000;
        printf("-100000000 -10000 %lld %lld\n", xx-1, yy);
    }
    return 0;
}

LRU management simulation [J]

Analog LRU algorithm:

  • Add a \ (block \) into the cache, if it already exists, it will be moved to the end
  • A query \ (Block \) is in the cache, if present, the output of its predecessor (-1) or it itself (0) or its successor (1) Data

And his teammates need to write together a large simulations on annoying. [Directly with string tle (how do not have the kind), so we need to be converted into digital].

Cattle customer evaluation Kyi ancestral TLE, as long as you have to try enough times, will be able to AC.

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

struct node {
    int pos;
    ll name;
    int val;
    bool operator < (const node &x) const {
        return pos < x.pos;
    }
};

set<node> SS;
unordered_map<ll, int> vis;

int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        SS.clear();
        vis.clear();
        int q, m;
        scanf("%d%d", &q, &m);
        int tot = 0;
        while(q--) {
            int op, v;
            char x[15];
            scanf("%d%s%d", &op, x, &v);
            int l = strlen(x);
            ll s = 0;
            for(int i = 0; i < l; i++) {
                s =  s*11+x[i]-'0';
            }
            if(op == 0) {
                if(vis[s] == 0) {
                    if(SS.size() == m) {
                        vis[SS.begin()->name] = 0;
                        SS.erase(SS.begin());
                    }
                    SS.insert(node{++tot, s, v});
                    vis[s] = tot;
                    printf("%d\n", v);
                }
                else {
                    auto it = SS.lower_bound(node{vis[s], 0, 0});
                    node temp = *it;
                    SS.erase(it);
                    temp.pos = ++tot;
                    SS.insert(temp);
                    vis[s] = tot;
                    printf("%d\n", temp.val);
                }
            }
            else if(op == 1){
                if(vis[s] == 0) {
                    printf("Invalid\n");
                }
                else {
                    auto it = SS.lower_bound(node{vis[s], 0, 0});
                    if(v == 0) {
                        printf("%d\n", (*it).val);
                    }
                    else if(v == 1) {
                        it++;
                        if(it == SS.end()) {
                            printf("Invalid\n");
                        }
                        else {
                            printf("%d\n", (*it).val);
                        }
                    }
                    else if(v == -1){
                        if(it == SS.begin()) {
                            printf("Invalid\n");
                        }
                        else {
                            it--;
                            printf("%d\n", (*it).val);
                        }
                    }
                }
            }   
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Decray/p/11278766.html