首页 > 其他分享 >多校联训 A 3

多校联训 A 3

时间:2022-10-05 20:44:46浏览次数:54  
标签:rt return int tree 多校 add 联训 mod

A.
考场上SB了,一个小细节写挂以为自己思路错误,直接就给弃了。

点击查看代码
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#warning fastread!
using namespace std;
const int N = 1E5 + 10,M = N, S = 2E6+10, TR = 4 * S, Q = N;
struct segment_tree{
    struct node{
        int sum;
    }tree[TR];
    void push_up(int rt){
        tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
    }
    void update(int rt, int v){
        tree[rt].sum += v;
    }
    void add(int rt, int l, int r, int s, int v){
        if(l >= r){
            assert(l == s);
            return update(rt, v);
        }
        int mid = (l + r) >> 1;
        if(s <= mid) add(rt<<1, l, mid, s, v);
        if(s > mid) add(rt<<1|1, mid + 1, r, s, v);
        push_up(rt);
    }
    int kth(int rt, int l, int r, int k){
        assert(k <= tree[rt].sum);
        if(l >= r){
            assert(tree[rt].sum >= 1);
            return l;
        }
        int mid = (l + r) >> 1;
        if(k <= tree[rt<<1].sum)
            return kth(rt<<1, l, mid, k);
        else
            return kth(rt<<1|1, mid + 1, r, k - tree[rt<<1].sum);
    }
    int rank(int rt, int l, int r, int s){ // <= 的元素个数
        if(l >= r){
            return tree[rt].sum;
        }
        int mid = (l + r) >> 1;
        if(s <= mid)
            return rank(rt<<1, l, mid, s);
        else
            return tree[rt<<1].sum + rank(rt<<1|1, mid + 1, r, s);
    }
}segt;
struct segment_tree_2{
    struct node{
        int mn, laz;
    }tree[TR];
    void update(int rt, int val){
        tree[rt].mn += val;
        tree[rt].laz+= val;
    }
    void push_down(int rt){
        if(tree[rt].laz != 0){
            update(rt<<1, tree[rt].laz);
            update(rt<<1|1, tree[rt].laz);
            tree[rt].laz = 0;
        }
    }
    void push_up(int rt){
        tree[rt].mn = min(tree[rt<<1].mn, tree[rt<<1|1].mn);
    }
    void modify(int rt, int l, int r, int s, int t, int val){
        if(s <=l && r <= t){
            return update(rt, val);
        }
        int mid = (l + r) >> 1;
        push_down(rt);
        if(s <= mid)
            modify(rt<<1, l, mid ,s ,t, val);
        if(t > mid)
            modify(rt<<1|1, mid + 1, r, s, t, val);
        push_up(rt);
    }
    int query(){
        return tree[1].mn;
    }
}bit;
vector<int> add[N];
int disc[S];
int a[N];
int myrk[M];
int sum[M];
int n, m, q;
struct t_q{
    int x, y, z;
}que[Q];
void prtrk(){
    cerr<<"rank = " << endl;
    for(int i = 1; i <= m; ++i){
        cerr<<myrk[i] <<" ";
    }
    cerr<<endl;
}
void reviewdata(){
    for(int i = 1; i <= n; ++i){
        cerr<< a[i] <<" ";
    }
    cerr<<endl;
    for(int i = 1; i <= m; ++i){
        cerr<<add[i].size() <<" ";
        for(int j = 0; j < add[i].size(); ++j){
            cerr<<add[i][j] <<" ";
        }
        cerr<<endl;
    }
    for(int i = 1; i <= q; ++i){
        cerr<<que[i].x <<" " << que[i].y <<" " << que[i].z <<endl;
    }
    cerr<<endl;   
}
int read(){
    int x = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();
    do{x = x * 10 + ch -'0',  ch = getchar();} while(isdigit(ch));
    return x;
}
int main(){
    n = read(), m = read(), q = read();
    for(int i = 1; i <= n; ++i) a[i] = read(), disc[++disc[0]] = a[i];
    for(int i = 1; i <= m; ++i){
        int x; 
        x = read();
        for(int j = 1; j <= x; ++j){
            int y; 
            y = read();
            add[i].push_back(y);
            disc[++disc[0]] = y;
        }
    }
    for(int i = 1; i <= q; ++i){
        int x, y, z;
        x = read(), y = read(), z = read();
        --y;
        que[i] = {x, y, z};
        disc[++disc[0]] = z;
    }
    sort(disc + 1, disc + 1 + disc[0]);
    disc[0] = unique(disc + 1, disc + 1 + disc[0]) - disc - 1;
    for(int i = 1; i <= n; ++i){
        a[i] = lower_bound(disc + 1, disc + 1 + disc[0], a[i]) - disc;
    }
    for(int i = 1; i <= m; ++i){
        for(int j = 0; j < add[i].size(); ++j){
            add[i][j] =  lower_bound(disc + 1, disc + 1 + disc[0], add[i][j]) - disc;
        }
        sum[i] = sum[i - 1] + add[i].size();
    }
    for(int i = 1; i<= q; ++i){
        que[i].z = lower_bound(disc + 1, disc + 1 + disc[0], que[i].z) - disc;
    }
    int rk = 0;
    for(int i = 2; i <= n; ++i){
        // segt.add(1, 1, disc[0], a[i], 1);
        if(a[i] < a[1]) ++ rk;
    }
    for(int i = 1; i <= m; ++i){
        myrk[i] = rk - sum[i];
        for(int j = 0; j < add[i].size(); ++j){
            // segt.add(1, 1, disc[0], add[i][j], 1);
            if(add[i][j] < a[1]) ++rk;
        }
    }
    for(int i = 1; i <= m; ++i)
        bit.modify(1, 1, m, i, i, myrk[i]);
    bool curans = true;
    curans = bit.query() >= 0;
    for(int i = 1; i <= q; ++i){
        int x = que[i].x, y = que[i].y, z = que[i].z;
        if((add[x][y] < a[1] && z < a[1]) || (add[x][y] > a[1] &&z > a[1])){
        } else if(add[x][y] < a[1] && z > a[1]){
            bit.modify(1, 1, m, x + 1, m, -1);
            curans = bit.query() >= 0;
        }else{
            assert(add[x][y] > a[1] && z < a[1]);
            bit.modify(1, 1, m, x + 1, m, 1);
            curans = bit.query() >= 0;
        }
        add[x][y] = z;
        printf("%d\n", (int)curans);
    }
    return 0;
}

B.连续段形预设DP
\(f(i, j)\)表示 选了\(i\)个数字,段数为\(j\),每次考虑往里面加入连续段或者合并连续段或者延伸连续段

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 400+10;
ll f[N][N];
int n;
ll mod;
int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n >> mod;
    f[0][0] = 1;
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= n; ++j){
                f[i][j] = (f[i][j] + f[i - 1][j - 1] * j % mod) % mod;
                f[i][j] = (f[i][j] + f[i - 1][j] * 2 * j % mod) % mod;
            if(i >= 2) f[i][j] = (f[i][j] + f[i - 2][j] * 2 * j % mod) % mod;
            if(i >= 2) f[i][j] = (f[i][j] + f[i - 2][j + 1] * j * 2 %mod) % mod;
            if(i >= 3) f[i][j] = (f[i][j] + f[i - 3][j + 1] * j% mod) % mod;
        }
    }
    cout <<f[n][1] << endl;
    return 0;
}

C暴力的平均复杂度\(O(2^n)\),没有卡,直接水过去了

D 构造题

#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10;
char str[N];
bool mp[N][N];
int n;
struct DSU{
    int fa[N], mx[N], mn[N], siz[N];
    void init(int len){
        for(int i = 1; i <= len; ++i) fa[i] = i, siz[i] = 1, mn[i] = i, mx[i] = i;
    }
    int find(int x){
        return x == fa[x] ? x : fa[x] = find(fa[x]);
    }
    void merge(int x, int y){
        x = find(x), y = find(y);
        if(x == y) return;
        if(siz[x] < siz[y]) swap(x, y);
        siz[x] += siz[y];
        fa[y] = x;
        mn[x] = min(mn[x], mn[y]);
        mx[x] = max(mx[x], mx[y]);
    }
    int gmax(int u){
        return mx[find(u)];
    }
    int gmin(int u){
        return mn[find(u)];
    }
}un;
void solve(int l, int r){
    // cerr<<"enter " << endl;
    vector<int> v;
    for(int i = l; i <= r; i = un.gmax(i) + 1) v.push_back(i);
	for(int i = 1; i < v.size(); ++i) un.merge(v.front(), v[i]);
    assert(v.size() > 3);
    cout << v.front() <<" " << v.back() <<endl;
    cout << v[1] <<" " << v.back() <<endl;
    for(int i = 2; i + 1 < v.size(); ++i){
        cout << v.front() << " "<< v[i] <<endl;
    }
    // cerr<<"out " << endl;
}
int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 1; i <= n; ++i){
        cin >> (str + 1);
        for(int j = i, k = 1; j <= n; ++j, ++k){
            mp[i][j] = str[k] - '0';
        }
    }
    // cerr<<"!"<<endl;
    un.init(n);
    for(int d = 2; d <= n; ++ d){
        for(int i = 1, j = i + d - 1; j <= n; ++i, ++j){
            if(mp[i][j] == 0) continue;
            if(un.find(i) == un.find(j)) continue;
            // cerr<<"i, j" << i <<" " << j << endl;
            if(un.gmax(i) + 1 == un.gmin(j)){
                cout << i <<" " << j << endl;
                un.merge(i, j);
            }else solve(i, j);
        }
    }
    return 0;
}

标签:rt,return,int,tree,多校,add,联训,mod
From: https://www.cnblogs.com/cdsidi/p/16756314.html

相关文章

  • 2022 牛客多校题解
    2022牛客多校题解Contest1JContest2JContest3HHack(SAM)枚举B中的右端点,查询最长在A串中向右可以延伸多长。考虑对A串建立一个SAM,然后对于B串从左到右跑SAM的D......
  • 2022杭电多校1
    1002Dragonslayer题目大意:给出一张的网格地图,给出起点和终点(均为方格的正中心),其中地图中有面墙阻隔了道路,每面墙都在网格线上并保证墙横平竖直,以线段端点的形式给,问......
  • 2021杭电多校1 J (普通莫队 树状数组)
    题意:给出1e5个二维平面上的坐标点0<=(x,y)<=1e5,1e5个询问,每次问x0,y0到x1,y1的矩阵中有多少y值不同的坐标点。思路:操作只有询问,不强制在线,数据范围1e5,就差把莫......
  • 2022杭电多校7
    这场难度有点大可改的题没几个B.IndependentFeedbackVertexSet题意:有1-n个点,每个点有权值。初始三个点的互相连接。接下来从第4个点开始,每次给出两个点,保证这两个......
  • 2022杭电多校8
    A.Theramore题意:给定一个01串,可以选择一个奇数长度的区间,使得该区间翻转,求任意次数操作后的最小字典序。分析:我们发现不管怎么转,奇数位置上的数永远在奇数上,偶数永远......
  • 2022杭电多校9
    J.SumPlusProduct题意:给定一个长度为n的数组,每次随机拿出两个数使其变成(a+b+a*b)再放回数组,最终数组中只剩下一个数,求剩余数字的期望是多少。分析:模拟一下......
  • 2022杭电多校10
    G.EvenTreeSplit题意:给定一个节点数为偶数的树,请问有多少种方案使得切割开一条边使得剩余连通块的大小都是偶数。分析:我们发现断开一条边是独立的,因为如果两个连通......
  • "蔚来杯"2022牛客暑期多校训练营5
    ADon'tStarve巧妙在于拓扑排序为啥要开滚动数组因为对于长度相同的边我们只能选择一条而这些边属于同一个状态的为了防止更新的时候对同状态的点造成影响#inclu......
  • "蔚来杯"2022牛客暑期多校训练营7
    A.FloorTilesinaPark给定\(W\timesH\)的矩阵,问将其分为\(k(k\leqslant5)\)个子矩阵的方案数。两个方案不同,当且仅当其切割方式不同手玩,画出所有\(k\leqslant5\)......
  • "蔚来杯"2022牛客暑期多校训练营9
    A CarShow题意:给定一个数组,请找到有多个区间[L,R]满足1到m的数都出现过。分析:直接双指针就好#include<bits/stdc++.h>usingnamespacestd;longlongn,m,s[......