kuangbin ---- segment you fly with a thematic tree (basic operation, a single point, interval updates and queries)


A

Meaning of the questions: q a given interrogation, single-point updates and queries

The main attention is writing templates

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<string>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
    char ch = getchar(); int x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
const int N = 5e5 + 10;
int num[4 * N];
int lazy[4 * N];
int T;
int n;
void pushup(int root)
{
    num[root] = num[root << 1] + num[root << 1 | 1];
}
void build(int l, int r, int root)
{
    if (l == r) {
        num[root] = 0; return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, root << 1);
    build(mid + 1, r, root << 1 | 1);
    pushup(root);
}
void update(int l, int r, int root, int pos, int val)
{
    if (l == r)
    {
        num[root] += val;
        return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid)update(l, mid, root << 1, pos, val);
    else update(mid + 1, r, root << 1 | 1, pos, val);
    pushup(root);
}
int querry(int l, int r, int root ,int lf, int rt)
{
    if (lf <= l && r <= rt)return num[root];
    int mid = (l + r) >> 1;
    int ans = 0;
    if (lf <= mid)ans+=querry(l, mid, root << 1, lf, rt);
    if (rt > mid)ans+=querry(mid + 1, r, root << 1 | 1, lf, rt);    
    return ans;
}
int main()
{
    T = read();
    for (int i = 1; i <= T; i++)
    {
        string s;
        n = read();
        build(1, n, 1);
        int x;
        up(i, 0, n)
        {
            x = read(); update(1, n, 1, i + 1, x);
        }
        printf("Case %d:\n", i);
        while (cin >> s && s != "End")
        {
            if (s == "Query")
            {
                int x, y; x = read(), y = read();
                cout << querry(1, n, 1, x, y) << endl;
            }
            if (s == "Add")
            {
                int p, v;
                p = read(), v = read();
                update(1, n, 1, p, v);
            }
            if (s == "Sub")
            {
                int p, v;
                p = read(), v = read();
                update(1, n, 1, p, -v);
            }
        }
    }
    return 0;
}

B

## meaning of the questions: single-point update, the maximum range queries, this situation needs to be updated to take advantage of pushup, every update back to the root node, and each time has been modified to change the most logn points to ensure that the time complexity.

C

Meaning of the questions: interval updates and queries.

Attention to the need flexible use of labeled lazy, lazy why should we mark because, for single-point update, we updated the downward along a chain up to logn nodes are updated to the complexity of the overall nlogn, and if the time zone update we still use more updated way, then when the time complexity nlogn * (each time interval length) then it is surely very easy to T off, after we joined lazy mark, every query and add only need to log times, marker as we traverse the tree for us to follow traversal, greatly reducing the time complexity.
------

D

Template, find the section covering different number. We can see that in essence, range dyeing, update interval, and overall I'm here to save the query for each color and then query the leaf nodes to see if the color been visited, if not answer +1. Also to mark the flexible use of lazy, first discretize, then update interval.

It is noteworthy that, when we talk discrete example, (1,10), (1,3), (5,10) of the range, if the range of 1-3 dyed it dyed a color, is 5-10 2 dyed colors, as well as 4 color, then 1-10, the answer is 3, if simple discrete, it would appear 1-10 query result is 2, 13510 think you dispersion became 1234, 1 3 4 update interval, can be found problems in three and five who should be added to a number between 35, 345 words would not be any problem.

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
    char ch = getchar(); int x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
const int N = 1e4 + 10;
vector<int>vec;
vector<pir>a;
int lazy[N << 4];
int num[N << 4];
int vis[N << 4];
int c,n,ans;
void pushdown(int root)
{
    if (lazy[root])
    {
        lazy[root << 1] = lazy[root];
        lazy[root << 1 | 1] = lazy[root];
        num[root << 1] = lazy[root];
        num[root << 1 | 1] = lazy[root];
        lazy[root] = 0;
    }
}
void build(int l, int r, int root)
{
    lazy[root] = 0;
    num[root] = 0;
    if (l == r) { return; }
    int mid = (l + r) >> 1;
    build(l, mid, root << 1);
    build(mid + 1, r, root << 1 | 1);
}
void update(int l, int r, int root, int val, int lf,int rt)
{
    if (lf <= l && r <= rt)
    {
        num[root] = val;
        lazy[root] = val;
        return;
    }
    pushdown(root);
    int mid = (l + r) >> 1;
    if (lf <= mid)update(l, mid, root << 1, val, lf, rt);
    if (rt > mid)update(mid + 1, r, root << 1 | 1, val, lf, rt);
}
void querry(int l, int r, int root,int pos)
{
    if (l == r)
    {
        if (num[root] == 0)return;
        //cout << "l" << l << "r" << r << endl;
        if (!vis[num[root]])
            ans++, vis[num[root]] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(root);
    if (mid < pos)querry(mid + 1, r, root << 1 | 1, pos);
    else querry(l, mid, root << 1, pos);
}
int main()
{
    c = read();
    while (c--)
    {
        ans = 0;
        n = read();
        memset(vis, 0, sizeof(vis));
        a.clear();
        vec.clear();
        int x, y;
        up(i, 0, n)
        {
            x = read(), y = read();
            vec.push_back(x), vec.push_back(y);
            a.push_back(make_pair(x, y));
        }
        sort(vec.begin(), vec.end());
        vec.erase(unique(vec.begin(), vec.end()), vec.end());
        int len = vec.size() - 1;
        up(i, 0, len)
        {
            if (vec[i] < vec[i + 1] - 1)
            {
                vec.push_back(vec[i] + 1);
            }
        }
        sort(vec.begin(), vec.end());
        vec.erase(unique(vec.begin(), vec.end()), vec.end());
        build(1, vec.size(), 1);
        up(i, 0, n)
        {
            int pos1 = lower_bound(vec.begin(), vec.end(), a[i].first) - vec.begin();
            int pos2 = lower_bound(vec.begin(), vec.end(), a[i].second) - vec.begin();
            pos1++, pos2++;
            update(1, vec.size(), 1, i + 1, pos1, pos2);
        }
        upd(i, 1,vec.size())
        {
            querry(1, vec.size(), 1, i);
        }
        cout << ans << endl;
    }
    return 0;
}

E

A whole range of update queries, every update, directly onto the whole interval, then under the mark.

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
    char ch = getchar(); int x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
const int N = 1e5 + 10;
int t, n, q;
int tree[N << 2];
int lazy[N << 2];
void pushup(int root)
{
    tree[root] = tree[root << 1] + tree[root << 1 | 1];
}
void pushdown(int l,int r,int root)
{
    if (lazy[root])
    {
        lazy[root << 1] = lazy[root];
        lazy[root << 1 | 1] = lazy[root];
        int mid = (l + r) >> 1;
        tree[root<<1] = lazy[root] * (mid - l + 1);
        tree[root << 1 | 1] = lazy[root] * (r - mid);
        lazy[root] = 0;
    }
}
void build(int l,int r,int root)
{
    lazy[root] = 0;
    if (l == r)
    {
        tree[root] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, root << 1);
    build(mid + 1, r, root << 1 | 1);
    pushup(root);
}
void update(int l, int r, int root, int lf, int rt,int val)
{
    if (lf <= l && r <= rt)
    {
        tree[root] = val * (r - l + 1);
        lazy[root] = val; return;
    }
    pushdown(l, r, root);
    int mid = (l + r) >> 1;
    if (lf <= mid)update(l, mid, root << 1, lf, rt, val);
    if(rt>mid) update(mid + 1, r, root << 1 | 1, lf, rt, val);
    pushup(root);
}
int querry(int l, int r, int root, int lf, int rt)
{
    if (lf <= l && r <= rt)
    {
        return tree[root];
    }
    pushdown(l,r,root);
    int mid = (l + r) >> 1;
    int ans = 0;
    if (lf <= mid)ans += querry(l, mid, root << 1, lf, rt);
    if (rt > mid)ans += querry(mid+1, r, root << 1 | 1, lf, rt);
    return ans;
}
int main()
{
    t = read();
    upd(i, 1, t)
    {
        n = read(), q = read();
        build(1, n, 1);
        while (q--)
        {
            int x, y, z;
            x = read(), y = read(), z = read();
            update(1, n, 1, x, y, z);
        }
        printf("Case %d: The total value of the hook is %d.\n", i, querry(1, n, 1, 1, n));
    }
    return 0;
}

F

Between ## and almost

G

A very interesting topic, and each time zone update, all val square root, the maximum range of the query. Since the inner int val then the maximum range, the square root becomes a maximum of 32, so we next to each layer to update all the points, and the length of the interval value (i.e., each value is the entire interval 1 ) skipped no longer updated. Overall, the upper limit is 32 * nlogn of complexity.

Pit that input x, y size relationship is uncertain.

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
    char ch = getchar(); int x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
const int N = 1e5 + 10;
ll tree[N << 2];
ll len[N << 2];
void pushup(int root)
{
    tree[root] = tree[root << 1] + tree[root << 1 | 1];
//  len[root] = len[root << 1] + len[root << 1 | 1];
}
void build(int l,int r,int root)
{
    tree[root] = 0;
    if (l == r) { scanf("%lld",&tree[root]); return; }
    int mid = (l + r) >> 1;
    build(l, mid, root << 1);
    build(mid + 1, r, root << 1 | 1);
    pushup(root);
}
void update(int l, int r, int root, int lf, int rt)
{
    if (l == r) { tree[root] = (ll)sqrt(tree[root]); return; }
    if (lf <= l && r <= rt&&tree[root]==r-l+1)
    {
        return;
    }
    int mid = (l + r) >> 1;
    if (lf <= mid)update(l, mid, root << 1, lf, rt);
    if (mid < rt)update(mid + 1, r, root << 1 | 1, lf, rt);
    pushup(root);
}
ll querry(int l, int r, int root, int lf, int rt)
{
    if (lf <= l && r <= rt)
    {
        return tree[root];
    }
    int mid = (l + r) >> 1;
    ll ans = 0;
    if (lf <= mid)ans += querry(l, mid, root << 1, lf, rt);
    if (rt > mid)ans += querry(mid + 1, r, root << 1 | 1, lf, rt);
    return ans;
}
int n,m;
int p = 0;
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        p++;
        ll x,y;
        int t;
        build(1, n, 1);
        m = read();
        printf("Case #%d:\n", p);
        up(i, 0, m)
        {
            t = read();
            scanf("%lld %lld", &x, &y);
            if (x > y)swap(x, y);
            if (t == 1)printf("%lld\n", querry(1, n, 1, x, y));
            if (t == 0)update(1, n, 1, x, y);
        }
        cout << endl;
    }
    return 0;
}

I

Meaning of the questions: to destroy every single point update a point, a point can also be reset, range query to the point of divergence can go far to both sides of the center.

There are two ideas, one is on this point approximately half the length, as is monotone

The second is the direct query, the title is equivalent to seeking continuous interval length, if we use divide and conquer idea to consider, line sequence containing interval length of the current node, either all the left-or-right, or across the middle. For this every time we have to maintain the current maintenance interval longest continuous interval left and right to the middle of the longest continuous interval interval interval and right sub-queries continuous access by right-left continuum subtree been left tree, then three cases can access to.

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
    char ch = getchar(); int x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
const int N = 5e4 + 10;
struct {
    int l, r;
}tree[N<<2];
int n, m;
stack<int >st;
void pushup(int root, int mid)
{
    tree[root].l = tree[root << 1].l;
    tree[root].r = tree[root << 1 | 1].r;
    if (tree[root].l == mid && tree[root << 1 | 1].l)tree[root].l = tree[root << 1 | 1].l;
    if (tree[root].r == mid + 1 && tree[root << 1].r)tree[root].r = tree[root << 1].r;
}
void build(int l, int r, int root)
{
    int mid = (l + r) >> 1;
    if (l == r) {
        tree[root].l = tree[root].r = l;
        return;
    }
    build(l, mid, root << 1);
    build(mid + 1, r, root << 1 | 1);
    pushup(root,mid);
}
void update(int l, int r, int root, int pos,int val)
{
    if (l == r)
    {
        if(val==0)
            tree[root].l = tree[root].r = 0;
        else tree[root].l = tree[root].r = l;
        return;
    }
    int mid = (l + r) >> 1;
    if (mid < pos)update(mid + 1, r, root << 1 | 1, pos, val);
    else update(l, mid, root << 1, pos, val);
    pushup(root,mid);
}
int querry(int l, int r, int root, int pos)
{
    if (l == r) {
        if (tree[root].l)return 1;
        else return 0;
    }
    if (tree[root].l&&tree[root].l >= pos)return tree[root].l - l + 1;
    if (tree[root].r&&tree[root].r <= pos)return r - tree[root].r + 1;
    int sum = 0;
    int mid = (l + r) >> 1;
    if (tree[root << 1].r&&tree[root << 1 | 1].l)
    {
        if (tree[root << 1].r <= pos && pos <= tree[root << 1 | 1].l)
            return tree[root << 1 | 1].l - tree[root << 1].r + 1;
    }
    if (pos <= mid)querry(l, mid, root << 1, pos);
    else querry(mid + 1, r, root << 1 | 1, pos);
}
char s[2];
int main()
{
    while (cin >> n>>m)
    {
        build(1, n, 1);
        while (!st.empty())st.pop();
        up(i, 0, m)
        {
            cin >> s;
            if (s[0] == 'D')
            {
                int x; x = read();
                update(1, n, 1, x, 0);
                st.push(x);
            }
            if (s[0] == 'R')
            {
                if (st.empty())continue;
                int top = st.top();
                st.pop();
                update(1, n, 1, top, 1);
            }
            if (s[0] == 'Q')
            {
                int x; x = read();
                printf("%d\n", querry(1, n, 1, x));
            }
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/LORDXX/p/11544527.html