• 2017 全国多校第九场 训练日志


    solved 3 (261/679)

    卡了题意,很难受

    Ch’s gift (LCA  或  树链剖分 + 线段树)

     思路:只要把主席树节点统计个数的意义改为累计所管辖区间的和就行了。剩下的部分就是裸的树上主席树了。

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 100010
    #define LOGN 20
    #define MAXQ 100010
    #define LL long long
    typedef struct {
        int to, next;
    } Edge;
    LL v[MAXN], dv[MAXN * 3], n, q, dvcnt;
    LL par[MAXN][LOGN], depth[MAXN];
    Edge edges[MAXN * 2];
    int head[MAXN], ecnt;
    
    void init() {
        memset(head, -1, sizeof(head));
        ecnt = 0;
        dvcnt = 0;
    }
    
    void add(int from, int to) {
        edges[ecnt].to = to;
        edges[ecnt].next = head[from];
        head[from] = ecnt++;
    }
    
    void dfs4lca(int root, int f) {
        par[root][0] = f, depth[root] = depth[f] + 1;
        for(int i = head[root]; ~i; i = edges[i].next) {
            int to = edges[i].to;
            if(to != f)dfs4lca(to, root);
        }
    }
    
    void prepare4lca() {
        dfs4lca(1, 0);
        for(int d = 0; d + 1 < LOGN; ++d) {
            for(int i = 1; i <= n; ++i) {
                if(par[i][d] == 0)par[i][d + 1] = 0;
                else par[i][d + 1] = par[par[i][d]][d];
            }
        }
    }
    
    int lca(int a, int b) {
        if(depth[a] < depth[b])swap(a, b);
        for(int i = LOGN - 1; i >= 0; i--) {
            int dif = depth[a] - depth[b];
            if((dif >> i) & 1)a = par[a][i];
        }
        if(a == b)return a;
        for(int i = LOGN - 1; i >= 0; --i) {
            if(par[a][i] != par[b][i]) {
                a = par[a][i], b = par[b][i];
            }
        }
        return par[a][0];
    }
    
    typedef struct {
        struct Node {
            int lch, rch;
            LL val;
        } nodes[MAXN * 20];
        int root[MAXN], ncnt;
    
        void init() {
            memset(nodes, 0, sizeof(nodes));
            memset(root, 0, sizeof(root));
            ncnt = 0;
        }
    private:
        void update0(int& croot, int proot, LL val, int idx, int l, int r) {
            if(croot == 0) {
                croot = ++ncnt;
                nodes[croot].val = nodes[proot].val + val;
            }
            if(l == r)return;
            int mid = (l + r) >> 1;
            if(idx <= mid) {
                nodes[croot].rch = nodes[proot].rch;
                update0(nodes[croot].lch, nodes[proot].lch, val, idx, l, mid);
            } else {
                nodes[croot].lch = nodes[proot].lch;
                update0(nodes[croot].rch, nodes[proot].rch, val, idx, mid + 1, r);
            }
        }
    public:
        void insert(int x, LL val, int idx) {
            update0(root[x], root[par[x][0]], val, idx, 1, dvcnt);
        }
    private:
        LL query0(int qlrt, int qrrt, int da, int db, int l, int r) {
            if(l >= da && r <= db)return nodes[qrrt].val - nodes[qlrt].val;
            int mid = (l + r) >> 1;
            LL res = 0;
            if(da <= mid)res += query0(nodes[qlrt].lch, nodes[qrrt].lch, da, db, l, mid);
            if(db > mid)res += query0(nodes[qlrt].rch, nodes[qrrt].rch, da, db, mid + 1, r);
            return res;
        }
    public:
        LL query(int ql, int qr, int da, int db, bool left_close) {
    //        printf("%d %d
    ", ql, par[ql][0]);
            if(left_close)return query0(root[par[ql][0]], root[qr], da, db, 1, dvcnt);
            else return query0(root[ql], root[qr], da, db, 1, dvcnt);
        }
    } PerSegTree;
    
    struct qqq {
        int ql, qr, a, b;
    } qs[MAXQ];
    
    #define indexOf(x) (lower_bound(dv + 1, dv + dvcnt + 1, x) - dv)
    PerSegTree pst;
    void buildPST(int root, int f) {
        pst.insert(root, v[root], indexOf(v[root]));
        for(int i = head[root]; ~i; i = edges[i].next) {
            int to = edges[i].to;
            if(to != f)buildPST(to, root);
        }
    }
    
    template<class T> inline void read(T& x) {
        bool s = 0;
        char t;
        while((t = getchar()) != '-' && (t < '0' || t > '9'));
        if(t == '-')s = 1, t = getchar();
        x = t - '0';
        while((t = getchar()) >= '0' && t <= '9')x = x * 10 + (t ^ 48);
        if(s)x = -x;
    }
    
    int main() {
    //    freopen("hdu6162.in", "r", stdin);
        int a, b;
        while(cin >> n >> q) {
            pst.init();
            init();
            for(int i = 1; i <= n; ++i)read(v[i]), dv[++dvcnt] = v[i];
            for(int i = 1; i < n; ++i) {
                read(a), read(b);
                add(a, b);
                add(b, a);
            }
            for(int i = 1; i <= q; ++i) {
                read(qs[i].ql), read(qs[i].qr), read(qs[i].a), read(qs[i].b);
                dv[++dvcnt] = qs[i].a;
                dv[++dvcnt] = qs[i].b;
            }
            prepare4lca();
            sort(dv + 1, dv + dvcnt + 1);
            dvcnt = unique(dv + 1, dv + dvcnt + 1) - dv;
            buildPST(1, 0);
            for(int i = 1; i <= q; ++i) {
                int s = qs[i].ql, t = qs[i].qr;
                int ilca = lca(s, t);
                LL sum = pst.query(ilca, s, indexOf(qs[i].a), indexOf(qs[i].b), 1)
                         + pst.query(ilca, t, indexOf(qs[i].a), indexOf(qs[i].b), 0);
                cout << sum << (i == q ? '
    ' : ' ');
            }
        }
        return 0;
    }

    FFF at Valentine (DFS)

    Senior Pan 

    Numbers

    Two strings (记忆化搜索 /  dp / 正则表达式 )

    题意:给一个s串,由大小写字母组成,给一个t串,由大小写字母和' . '和' * '组成,其中点可以替换任何字符,星可以改变前面那个字符的任意长度(0到正无穷),能否匹配s和t?

    思路:记忆化搜索

    1.dfs(i,j)表示s[i]和t[j]匹配

    那么对于t[j],分3种情况

    1.1 : t[j]为' . '那么,我们可以dfs(i+1,j+1),表示i和j匹配成功,那么用掉i和j之后,比较(i+1,j+1),同时,注意在dfs下去之前,把t[j]修改成s[i],在dfs结束之后修改回' . '

    1.2 : t[j]为星,首先可以跳过这个星串,直接dfs(i,j+2)。

    接下来,我们只需要:

    看i是否和j-1匹配,如果匹配,dfs(i+1,j),表示*保留着继续搜,dfs(i+1,j+1),表示*不保留了。

    1.3 : t[j]== s[i] 直接往下搜便可 dfs(i+1,j+1)

    如果t[j+1]是星,那么我们还可以dfs一次dfs(i,j+2)

    判断可行的标准有:

    i和j都超出了s串和t串的长度

    i超出长度,j刚好在t串尾部,且尾部为星

    i超出长度,j在尾部-1的位置,且尾部为星

    由于每种情况搜了一次就不再继续搜,所以复杂度是O(2500*2500*T)

    #include <bits/stdc++.h>
    using namespace std;
    string s,t;
    int ok;
    bool vis[2600][2600];
    int dfs(int i,int j){
        if(vis[i][j])return vis[i][j];
        if(i==s.size()&&j==t.size()){
            ok=1;
            return vis[i][j]=1;
        }
        if(i==s.size()&&j==t.size()-1&&t[j]=='*'){
            ok=1;
            return vis[i][j]=1;
        }
        if(i==s.size()&&j==t.size()-2&&t[j+1]=='*'){
            ok=1;
            return vis[i][j]=1;
        }
        if(ok){
            return vis[i][j]=1;
        }
        if(i==s.size())return vis[i][j]=-1;
    
        if(t[j]=='.'){
            t[j]=s[i];
            vis[i+1][j+1]=dfs(i+1,j+1);
            t[j]='.';
            if(j+1<t.size() && t[j+1]=='*'){
                vis[i][j+2]=dfs(i,j+2);
            }
        } else if(t[j]=='*'){
            vis[i][j+1]=dfs(i,j+1);
            if(t[j-1]=='.'){
                vis[i+1][j]=dfs(i+1,j);
                vis[i+1][j+1]=dfs(i+1,j+1);
            }else{
                if(s[i]==t[j-1]){
                    vis[i+1][j+1]=dfs(i+1,j+1);
                    vis[i+1][j]=dfs(i+1,j);
                }
            }
        } else {
            if(s[i]==t[j]){
                vis[i+1][j+1]=dfs(i+1,j+1);
            }
            if(j+1<t.size() && t[j+1]=='*'){
                vis[i][j+2]=dfs(i,j+2);
            }
        }
    }
    
    int main(){
        int T;cin>>T;
        while(T--){
            memset(vis,0,sizeof vis);
            cin>>s>>t;
            ok=0;
            dfs(0,0);
            printf("%s
    ",ok ? "yes":"no");
        }
        return 0;
    }
  • 相关阅读:
    flutter-布局(水平和垂直)
    flutter-GridView(网格列表)
    flutter-ListView(列表组件)
    flutter-图片组件(Image)的使用
    flutter-container-容器
    flutter-hello flutter 并且修改字体
    nginx
    初步学习next.js-7-打包
    初步学习next.js-6-使用antd
    初步学习next.js-5-编写css样式和lazyloading
  • 原文地址:https://www.cnblogs.com/dowhile0/p/9189964.html
Copyright © 2020-2023  润新知