ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022.8.3 颓废记录

2022-08-04 00:31:10  阅读:171  来源: 互联网

标签:le 颓废 记录 int top maxn 2022.8 return id


Preface

数据结构题太珂怕了QAQ

Content

[CF165D]Beard Graph

给定一棵 \(n\) 个结点的数,初始所有边均为黑边,\(m\) 次操作,操作分 \(3\) 种:

  • 1 u:把第 \(u\) 条边变成黑边。

  • 2 u:把第 \(u\) 条边变成白边

  • 3 u v:若 \((u,v)\) 路径上存在白边则输出 -1,否则输出路径上的黑边数量。

\(1 \le n \le 10^5,1\le m \le 3\times 10^5\)

树剖模板,就当复习树剖了qwq。

时间复杂度 \(O(M\log^2N)\)

Code

// Problem: CF165D Beard Graph
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF165D
// Memory Limit: 250 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
using namespace std;
const int maxn = 1e5 + 5;
int f[maxn],d[maxn],son[maxn],sz[maxn],top[maxn],rk[maxn],id[maxn],cnt;
int ls[maxn << 2],rs[maxn << 2],sum[maxn << 2];
void pushup(int i) {
    sum[i] = sum[i << 1] + sum[i << 1 | 1];
    return ;
}
void build(int i,int l,int r) {
    ls[i] = l;
    rs[i] = r;
    if(l == r) {
        sum[i] = 1;
        return ;
    }
    int mid = l + r >> 1;
    build(i << 1 , l , mid);
    build(i << 1 | 1 , mid + 1 , r);
    pushup(i);
    return ;
}
void modify(int i,int pos,int val) {
    if(ls[i] == rs[i]) {
        sum[i] = val;
        return ;
    }
    int mid = ls[i] + rs[i] >> 1;
    if(pos <= mid)modify(i << 1 , pos , val);
    else modify(i << 1 | 1 , pos , val);
    pushup(i);
    return ;
}
int query(int i,int l,int r) {
    if(ls[i] >= l&&rs[i] <= r)return sum[i];
    if(ls[i] > r||rs[i] < l)return 0;
    int mid = ls[i] + rs[i] >> 1,s = 0;
    if(l <= mid)s += query(i << 1 , l , r);
    if(r > mid)s += query(i << 1 | 1 , l , r);
    return s;
}
int n;
struct edge {
    int u,v;
    edge() {
        u = v = 0;
    }
}E[maxn];
vector<int> G[maxn];
void dfs1(int u,int fa) {
    sz[u] = 1;
    for(auto& v : G[u]) {
        if(v == fa)continue ;
        f[v] = u;
        d[v] = d[u] + 1;
        dfs1(v , u);
        sz[u] += sz[v];
        if(sz[v] > sz[son[u]])son[u] = v;
    }
    return ;
}
void dfs2(int u,int tp) {
    top[rk[id[u] = ++ cnt] = u] = tp;
    if(!son[u])return ;
    dfs2(son[u] , tp);
    for(auto& v : G[u]) {
        if(v == f[u]||v == son[u])continue ;
        dfs2(v , v);
    }
    return ;
}
int findans(int x,int y) {
    int ans = 0,tot = 0;
    while(top[x] != top[y]) {
        if(d[top[x]] < d[top[y]])swap(x , y);
        ans += query(1 , id[top[x]] , id[x]);
        tot += id[x] - id[top[x]] + 1;
        if(ans != tot)return -1;
        x = f[top[x]];
    }
    if(id[x] > id[y])swap(x , y);
    if(id[x] < id[y])ans += query(1 , id[x] + 1 , id[y]);
    tot += id[y] - id[x];
    return ans == tot ? ans : -1;
}
int main() {
    scanf("%d",&n);
    for(int i = 1;i < n;++ i) {
        scanf("%d %d",&E[i].u,&E[i].v);
        G[E[i].u].pb(E[i].v);
        G[E[i].v].pb(E[i].u);
    }
    dfs1(1 , 0);
    dfs2(1 , 1);
    build(1 , 1 , n);
    int Q;
    scanf("%d",&Q);
    while(Q --) {
        int op,x,y;
        scanf("%d %d",&op,&x);
        if(op == 1) {
            if(f[E[x].u] == E[x].v) {
                modify(1 , id[E[x].u] , 1);
            }
            else {
                modify(1 , id[E[x].v] , 1);
            }
        }
        else if(op == 2) {
            if(f[E[x].u] == E[x].v) {
                modify(1 , id[E[x].u] , 0);
            }
            else {
                modify(1 , id[E[x].v] , 0);
            }
        }
        else {
            scanf("%d",&y);
            printf("%d\n",findans(x , y));
        }
    }
    return 0;
}

[CF899F]Letters Removing

给定一个长度为 \(n\) 的,含 \(0\sim 9,a\sim z,A\sim Z\) 的字符串,\(m\) 次操作,每次删除一段区间内的所有为 \(c\) 的字符,输出删除完毕后的字符串。

串的总长度为 \(n\),则总的删除次数不超过 \(n\),这启发我们暴力操作。

std::setstd::vector 存下每种字符的位置,每次二分出位置暴力删除,总时间复杂度 \(O(m\log n)\)。

但有一个问题:删除操作会对后面的字符串产生影响,输入的区间并不一定是要删除的区间。

这是一个经典的问题,考虑用一个树状数组维护 \(1\sim n\) 的位置上是否有字符,然后用倍增+树状数组求出前缀和为 \(l,r\) 的第一个位置。

总时间复杂度 \(O(m\log n)\)。

Code

// Problem: CF899F Letters Removing
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF899F
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define Chtholly set<int>::iterator
using namespace std;
const int maxn = 2e5 + 5;
char t[maxn];
int n,m;
int c[maxn];
set<int> s[65];
int lev(char x) {
    if(x >= '0'&&x <= '9')return x - '0';
    if(x >= 'a'&&x <= 'z')return 10 + x - 'a';
    if(x >= 'A'&&x <= 'Z')return 36 + x - 'A';
}
int lowbit(int x) {
    return x & -x;
}
void add(int x,int y) {
    for(;x <= n;x += lowbit(x))c[x] += y;
    return ;
}
int query(int x) {
    int ans = 0,cnt = 0;
    for(int p = 17;~ p;-- p) {
        if(ans + (1 << p) <= n&&cnt + c[ans + (1 << p)] < x) {
            cnt += c[ans + (1 << p)];
            ans += 1 << p;
        }
    }
    return ans + 1;
}
int Query(int x) {
    int ans = 0;
    for(;x;x -= lowbit(x))ans += c[x];
    return ans;
}
int main() {
    scanf("%d %d",&n,&m);
    scanf("%s",t + 1);
    for(int i = 1;i <= n;++ i)add(i , 1),s[lev(t[i])].insert(i);
    for(int i = 1;i <= m;++ i) {
        int l,r;
        char c;
        scanf("%d %d %c",&l,&r,&c);
        l = query(l);
        r = query(r);
        if(s[lev(c)].empty())continue ;
        Chtholly itl = s[lev(c)].lower_bound(l),itr = s[lev(c)].upper_bound(r);
        for(Chtholly it = itl;it != itr;++ it)add(*it , -1);
        s[lev(c)].erase(itl , itr);
    }
    for(int i = 1;i <= n;++ i) {
        if(Query(i) - Query(i - 1) > 0)printf("%c",t[i]);
    }
    return 0;
}

[CF979D]Kuro and GCD and XOR and SUM

初始有一个空集合,\(Q\) 次操作。操作分两种:

  • 1 u:将 \(u\) 加入集合。

  • 2 x k s:求一个最大的 \(v\),使得:

  1. \(v + x \le s\)

  2. \(k\mid \gcd(v,x)\)

  3. \(x\oplus v\) 最大(\(\oplus\) 表示按位异或)

如果不存在这样的 \(v\),输出 \(-1\)。

\(1 \le Q,u,x,k,s \le 10^5\)

首先,\(k \mid \gcd(v,x)\) 显然可以转化为 \(k\mid v\land k\mid x\)。

因为要求的是一个值域内的异或最大值,显然要用到字典树。

综上,考虑对 \(1\sim V\)(\(V\) 表示值域)中的每个数建立一棵字典树。

插入操作就是把 \(u\) 插如所有 \(d(d\mid u)\) 对应的字典树。

查询时先判断是否存在 \(v\),若存在,则在 \(k\) 的字典树中查询。

由于 \(1\sim V\) 中约数个数约为 \(V\log V\),每个数的约数均摊下来是 \(\log V\) 个,故时空复杂度为 \(O(V\log^2 V)\)。

(CF 的数据没那么毒瘤,大概率是不会卡的。。吧)

// Problem: CF979D Kuro and GCD and XOR and SUM
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF979D
// Memory Limit: 500 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
using namespace std;
const int maxn = 1e5 + 5;
const int m = 1e5;//value
vector<int> G[maxn];
int rt[maxn],trie[maxn * 400][2],minv[maxn * 400],cnt;
void insert(int x,int y) {
    if(!rt[x])rt[x] = ++ cnt;
    int u = rt[x];
    minv[u] = min(minv[u] , y);
    for(int k = 17;~ k;-- k) {
        int c = y >> k & 1;
        if(!trie[u][c])trie[u][c] = ++ cnt;
        u = trie[u][c];
        minv[u] = min(minv[u] , y);
    }
    return ;
}
int query(int r,int x,int y) {
    int u = rt[r];
    if(minv[u] > y)return -1;
    for(int k = 17;~ k;-- k) {
        int c = x >> k & 1;
        c ^= 1;
        if(trie[u][c]&&minv[trie[u][c]] <= y)  {
            u = trie[u][c];
        }
        else {
            u = trie[u][c ^ 1];
        }
    }
    return minv[u];
}
int main() {
    for(int i = 1;i <= m;++ i) {
        for(int j = i;j <= m;j += i) {
            G[j].pb(i);
        }
    }
    memset(minv , 0x3f , sizeof(minv));
    int Q;
    scanf("%d",&Q);
    while(Q --) {
        int op,x,y,z;
        scanf("%d %d",&op,&x);
        if(op & 1) {
            for(auto& v : G[x]) {
                insert(v , x);
            }
        }
        else {
            scanf("%d %d",&y,&z);
            if(x % y) {
                puts("-1");
                continue ;
            }
            printf("%d\n",query(y , x , z - x));
        }
    }
    return 0;
}

美好的回忆:

真好玩哈哈(砸桌子)

[NOIP2020]字符串匹配

题解

标签:le,颓废,记录,int,top,maxn,2022.8,return,id
来源: https://www.cnblogs.com/Royaka/p/16549261.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有