zoukankan      html  css  js  c++  java
  • 20171028洛谷NOIP模拟

    传送门

    题目分析:

    A:对一个初始值全部为0的序列进行一系列的区间修改(加)和询问(某一区间中满足(min le a_i * i \% mod le max)的元素个数)。
    第一眼看第一题怎么也想不出什么妙招,仔细分析复杂度才知道这就是一道暴力模拟+优化。
    对于前面的修改,维护差分,对于仅有的1000次询问,每次都遍历累计前缀和并计算答案。
    对于后面的大量询问,必须使用O(1)的算法,维护前缀和,直接回答。

    B: 待填

    C: 给一棵树,每次可以1.删除某一条边,2.询问某两点是否联通, 3.恢复某一条边
    考试完了下来一写立刻就1A了,这道题又不只一种方法,我知道的有:

    1. LCT(卡常90分)
    2. 树链剖分
    3. 差分
      树链剖分的做法:将每个点的权值设置为1,树链剖分维护线段树。
      对于1操作:将深度较大的那个点的权值减1。
      对于3操作:将深度较大的那个点的权值加1。
      对于2操作:先计算出两点间的距离((dis = dep[u] + dep[v] - 2 * dep[lca])),然后再在线段树上求出该路径除去lca的权值和V,如果(V == dis),那么两点联通,否则不连通。
      附上差分的题解:

    考试总结:

    1. 第一题一般来说是简单题,就算没做出来也不要在其上花费太多时间。
    2. 打完自己有把握的题后不要着急离开,一定要打对拍保证正确,正解爆0也是常有的事。
    3. 如果看到某题脑子空白了就先放放或者放松放松,清醒才能思考。

    code

    A:

    #include<bits/stdc++.h>
    using namespace std;
    namespace IO{
        template<typename T>
        inline void read(T &x){
            T i = 0, f = 1;
            char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') ch = getchar(), f = -1;
            for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
            x =  i * f;
        }
        template<typename T>
        inline void wr(T x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wr(x / 10);
            putchar(x % 10 + '0');
        }
    }using namespace IO;
    
    const int N = 80050;
    typedef long long ll;
    const ll OO = 2e18;
    int n, opt;
    ll a[N], b[N];
    ll mod, minn, maxx;
    
    inline bool check(int x, ll *y){
        return minn <= 1ll * x * y[x] % mod && 1ll * x * y[x] % mod <= maxx;
    }
    
    int main(){
        freopen("h.in", "r", stdin);
        read(n), read(opt), read(mod), read(minn), read(maxx);
        for(int i = 1; i <= opt; i++){
            char opts[10]; scanf("%s", opts + 1);
            if(opts[1] == 'A'){
                int l, r; read(l), read(r);
                ll x; read(x);
                a[l] += x, a[r + 1] -= x;
            }
            else if(opts[1] == 'Q'){
                int l, r, ans = 0; read(l), read(r);
                for(int i = 1; i <= r; i++){
                    b[i] = a[i] + b[i - 1];
                    if(i >= l && check(i, b)) ans++;
                }
                wr(ans);
                putchar('
    ');
            }
        }
        for(int i = 1; i <= n; i++){
            a[i] += a[i - 1];
            b[i] = (check(i, a) ? 1 : 0) + b[i - 1];
        }
        read(opt);
        for(int i = 1; i <= opt; i++){
            int l, r; read(l), read(r);
            wr(b[r] - b[l - 1]);
            putchar('
    ');
        }
        return 0;
    }
    

    B: 待填

    C:

    #include<bits/stdc++.h>
    using namespace std;
    namespace IO{
        template<typename T>
        inline void read(T &x){
            T i = 0, f = 1;
            char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') ch = getchar(), f = -1;
            for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
            x =  i * f;
        }
        template<typename T>
        inline void wr(T x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wr(x / 10);
            putchar(x % 10 + '0');
        }
    }using namespace IO;
    
    const int N = 300005, M = 300005;
    int n, m;
    int ecnt, adj[N], nxt[N << 1], go[N << 1];
    vector<pair<int, int> > reg;
    
    inline void addEdge(int u, int v){
        nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v;
    }
    
    namespace SegTree{
        int tree[N << 2];
        inline void upt(int k){
            tree[k] = tree[k << 1] + tree[k << 1 | 1];
        }
        inline void build(int k, int l, int r){
            if(l == r){
                tree[k] = 1;
                return;
            }
            int mid = l + r >> 1;
            build(k << 1, l, mid);
            build(k << 1 | 1, mid + 1, r);
            upt(k);
        }
        inline void modify(int k, int l, int r, int pos, int v){
            if(l == r){
                tree[k] += v;
                return;
            }
            int mid = l + r >> 1;
            if(pos <= mid) modify(k << 1, l, mid, pos, v);
            else modify(k << 1 | 1, mid + 1, r, pos, v);
            upt(k);
        }
        inline int query(int k, int l, int r, int x, int y){
            if(x <= l && r <= y) return tree[k];
            int mid = l + r >> 1;
            int ret = 0;
            if(x <= mid) ret += query(k << 1, l, mid, x, y);
            if(y > mid) ret += query(k << 1 | 1, mid + 1, r, x, y);
            return ret;
        }
    }
    
    namespace Tree{
        int dep[N], fa[N], top[N], pos[N], idx[N], tot, sze[N], son[N];
        inline void dfs1(int u, int f){
            fa[u] = f;
            dep[u] = dep[f] + 1;
            sze[u] = 1;
            for(int e = adj[u]; e; e = nxt[e]){
                int v = go[e];
                if(v == f) continue;
                dfs1(v, u);
                sze[u] += sze[v];
                if(sze[v] > sze[son[u]] || !son[u]) son[u] = v;
            }
        }
        inline void dfs2(int u, int f){
            if(son[u]){
                idx[pos[son[u]] = ++tot] = son[u];
                top[son[u]] = top[u];
                dfs2(son[u], u);
            }
            for(int e = adj[u]; e; e = nxt[e]){
                int v = go[e];
                if(v == f || v == son[u]) continue;
                idx[pos[v] = ++tot] = v;
                top[v] = v;
                dfs2(v, u);
            }
        }
        inline void splitTree(){
            dfs1(1, 0);
            top[tot = pos[1] = idx[1] = 1] = 1;
            dfs2(1, 0);
            SegTree::build(1, 1, n);
        }
        inline int getLca(int u, int v){
            while(top[u] != top[v]){
                if(dep[top[u]] < dep[top[v]]) swap(u, v);
                u = fa[top[u]];
            }
            return dep[u] < dep[v] ? u : v;
        }
        inline int pathQuery(int p, int q){
            int ret = 0;
            while(top[p] != top[q]){
                if(dep[top[p]] < dep[top[q]]) swap(p, q);
                ret += SegTree::query(1, 1, n, pos[top[p]], pos[p]);
                p = fa[top[p]];
            }
            if(dep[p] > dep[q]) swap(p, q);
            /*略过lca*/
            ret += SegTree::query(1, 1, n, pos[p] + 1, pos[q]);
            return ret;
        }
    }
    
    int main(){
        freopen("h.in", "r", stdin);
        read(n), read(m);
        for(int i = 1; i < n; i++){
            int x, y; read(x),  read(y);
            addEdge(x, y), addEdge(y, x);
        }
        Tree::splitTree();
        for(int i = 1; i <= m; i++){
            char opt[5]; scanf("%s", opt + 1);
            if(opt[1] == 'Q'){
                int p, q; read(p), read(q);
                int lca = Tree::getLca(p, q);
                int dis1 = Tree::pathQuery(p, q), dis2 = Tree::dep[p] + Tree::dep[q] - 2 * Tree::dep[lca];
                if(dis1 != dis2)
                    printf("No
    ");
                else printf("Yes
    ");
            }
            else if(opt[1] == 'C'){
                int p, q; read(p), read(q);
                if(Tree::dep[p] < Tree::dep[q]) swap(p, q);
                SegTree::modify(1, 1, n, Tree::pos[p], -1);
                reg.push_back(make_pair(p, q));
            }
            else{
                int x; read(x);
                pair<int, int> c = reg[x - 1];
                /*放入reg时已经保证first是深度较大的*/
                SegTree::modify(1, 1, n, Tree::pos[c.first], 1);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    使用QT在子线程中访问串口
    小程序批量上传图片方案
    Jenkins自动化远程部署(vue-github)
    nginx配置https证书
    Linux 安装php7
    Vue技术点整理-指令
    如何保证接口的幂等性?
    mybatis 一对多分页查询数据条数不匹配解决
    源码系列-JDK-String
    kafka window 操作
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7748181.html
Copyright © 2011-2022 走看看