[线段树专场 题解]sustoj_线段树进阶(懒惰标记,离散化,可持久化) + 树链剖分 题解

题目地址

A. 帝国时代:罗马复兴

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9 + 1;;
const int maxn = 1e5 + 10;
struct node {
  int Max, Min, lazy;
} segtree[maxn << 2];
struct edge {
  int to, next;
} edge[maxn << 2];
int head[maxn], fa[maxn], zson[maxn], size[maxn], dfsid[maxn], rnk[maxn], top[maxn], dep[maxn], a[maxn];
int n, m, cnt, tot, u, v, x;
char s[10];

void init() {
  memset(segtree, 0, sizeof segtree);
  memset(edge, 0, sizeof edge);
  memset(head, 0, sizeof head);
  memset(fa, 0, sizeof fa);
  memset(zson, 0, sizeof zson);
  memset(size, 0, sizeof size);
  memset(dfsid, 0, sizeof dfsid);
  memset(rnk, 0, sizeof rnk);
  memset(top, 0, sizeof top);
  memset(dep, 0, sizeof dep);
  memset(a, 0, sizeof a);
  cnt = tot = 0;
}

void add_edge(int x, int y) {
  edge[++tot].next = head[x];
  edge[tot].to = y;
  head[x] = tot;
}

void dfs1(int x, int f, int deep) {
  dep[x] = deep;
  fa[x] = f;
  size[x] = 1;
  for (int i = head[x]; i; i = edge[i].next) {
    int son = edge[i].to;
    if (son == f) continue;
    dfs1(son, x, deep + 1);
    size[x] += size[son];
    if (size[son] > size[zson[x]]) {
      zson[x] = son;
    }
  }
}

void dfs2(int x, int t) {
  dfsid[x] = ++cnt;
  rnk[cnt] = x;
  top[x] = t;
  if(zson[x] == 0) return;
  dfs2(zson[x], t);
  for (int i = head[x]; i; i = edge[i].next) {
    int son = edge[i].to;
    if (son == fa[x] || son == zson[x]) continue;
    dfs2(son, son);
  }
}

void nega(int now) {
  int t = 0 - segtree[now].Max;
  segtree[now].Max = 0 - segtree[now].Min;
  segtree[now].Min = t;
}

void pushdown(int now) {
  if (!segtree[now].lazy%2) return;
  segtree[now << 1].lazy += 1;
  segtree[(now << 1)|1].lazy += 1;
  if (segtree[now << 1].lazy%2) nega(now << 1);
  if (segtree[(now << 1)|1].lazy%2) nega((now << 1)|1);
  segtree[now].lazy = 0;
}

void pushup(int now) {
  segtree[now].Max = max(segtree[now << 1].Max, segtree[(now << 1)|1].Max);
  segtree[now].Min = min(segtree[now << 1].Min, segtree[(now << 1)|1].Min);
}

void build_tree(int l, int r, int now) {
  if (l == r) {
    segtree[now].Max = segtree[now].Min = a[rnk[l]];
    return;
  }
  int mid = l + (r - l)/2;
  build_tree(l, mid, now << 1);
  build_tree(mid + 1, r, (now << 1)|1);
  pushup(now);
}

void update(int L, int R, int l, int r, int now) {
  if (L <= l && R >= r) {
    segtree[now].lazy += 1;
    if(segtree[now].lazy%2) nega(now);
    return;
  }
  pushdown(now);
  int mid = l + (r - l)/2;
  if (L <= mid) update(L, R, l, mid, now << 1);
  if (R > mid) update(L, R, mid + 1, r, (now << 1)|1);
  pushup(now);
}

void modify(int l, int r, int tar, int c, int now) {
  if (l == r) {
    segtree[now].Max = segtree[now].Min = c;
    return;
  }
  pushdown(now);
  int mid = l + (r - l)/2;
  if (tar <= mid) modify(l, mid, tar, c, now << 1);
  else modify(mid + 1, r, tar, c, (now << 1)|1);
  pushup(now);
}

int query(int L, int R, int l, int r, int now) {
  if (L <= l && R >= r) {
    return segtree[now].Max;
  }
  pushdown(now);
  int mid = l + (r - l)/2, ans = -INF;
  if (L <= mid) ans = max(ans, query(L, R, l, mid, now << 1));
  if (R > mid) ans = max(ans, query(L, R, mid + 1, r, (now << 1)|1));
  return ans;
}

void line_nega(int x, int y) {
  int tx = top[x], ty = top[y];
  while (tx != ty) {
    if (dep[tx] >= dep[ty]) {
      update(dfsid[tx], dfsid[x], 1, n, 1);
      x = fa[tx];
    } else {
      update(dfsid[ty], dfsid[y], 1, n, 1);
      y = fa[y];
    }
    tx = top[x], ty = top[y];
  }
  if (dep[x] <= dep[y]) {
    update(dfsid[x], dfsid[y], 1, n, 1);
  } else {
    update(dfsid[y], dfsid[x], 1, n, 1);
  }
}

int find(int x, int y) {
  int tx = top[x], ty = top[y], Max = -INF;
  while (tx != ty) {
    if (dep[tx] >= dep[ty]) {
      Max = max(Max, query(dfsid[tx], dfsid[x], 1, n, 1));
      x = fa[tx];
    } else {
      Max = max(Max, query(dfsid[ty], dfsid[y], 1, n, 1));
      y = fa[y];
    }
    tx = top[x], ty = top[y];
  }
  if (dep[x] <= dep[y]) {
    Max = max(Max, query(dfsid[x], dfsid[y], 1, n, 1));
  } else {
    Max = max(Max, query(dfsid[y], dfsid[x], 1, n, 1));
  }
  return Max;
}

int main()
{
  //freopen("test.in", "r", stdin);
  //freopen("test.out", "w", stdout);

  while (scanf("%d %d", &n, &m) != EOF) {

    init();

    for (int i = 1; i <= n; i++) {
      scanf("%d", &a[i]);
    }
    for (int i = 0; i < n - 1; i++) {
      scanf("%d %d", &u, &v);
      add_edge(u, v);
      add_edge(v, u);
    }

    dfs1(1, -1, 1);
    dfs2(1, 1);
    build_tree(1, n, 1);

    for (int i = 0; i < m; i++) {
      scanf("%s", s);
      if (s[0] == 'c') {
        scanf("%d %d", &u, &x);
        modify(1, n, dfsid[u], x, 1);
      } else if (s[0] == 'n') {
        scanf("%d %d", &u, &v);
        line_nega(u, v);
      } else {
        scanf("%d %d", &u, &v);
        printf("%d\n", find(u, v));
      }
    }

  }

  return 0;
}

B. 反恐精英:全球攻势

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <bitset>
#include <algorithm>
using namespace std;
#define lson	th << 1
#define rson	th << 1 | 1
typedef long long	ll;
typedef long double	ldb;
#define inf	999999999
#define pi	acos( -1.0 )
#define maxn	100010
struct edge {
	int to, next;
}	e[2 * maxn];
int	pos, tot, Lc, Rc;
int	top[maxn], son[maxn], fa[maxn], dep[maxn], num[maxn], p[maxn], a[maxn], c[maxn], first[maxn];
void dfs1( int u, int pre, int deep )
{
	int i, j, v;
	dep[u]	= deep;
	fa[u]	= pre;
	num[u]	= 1;
	for ( i = first[u]; i != -1; i = e[i].next )
	{
		v = e[i].to;
		if ( v == pre )
			continue;
		dfs1( v, u, deep + 1 );
		num[u] += num[v];
		if ( son[u] == -1 || num[son[u]] < num[v] )
			son[u] = v;
	}
}


void dfs2( int u, int tp )
{
	int i, j, v;
	top[u] = tp;
	if ( son[u] != -1 )
	{
		p[u] = ++pos; c[pos] = a[u]; dfs2( son[u], tp );
	}else  {
		p[u] = ++pos; c[pos] = a[u]; return;
	}
	for ( i = first[u]; i != -1; i = e[i].next )
	{
		v = e[i].to;
		if ( v == son[u] || v == fa[u] )
			continue;
		dfs2( v, v );
	}
}


struct node {
	int l, r, num, cl, cr, flag;
} b[4 * maxn];
void pushup( int th )
{
	b[th].cl	= b[lson].cl;
	b[th].cr	= b[rson].cr;
	b[th].num	= b[lson].num + b[rson].num;
	if ( b[lson].cr == b[rson].cl )
		b[th].num--;
}


void pushdown( int th )
{
	if ( b[th].flag == 1 )
	{
		b[lson].flag	= b[rson].flag = 1;
		b[lson].cl	= b[lson].cr = b[rson].cl = b[rson].cr = b[th].cl;
		b[lson].num	= b[rson].num = 1;
		b[th].flag	= -1;
	}
}


void build( int l, int r, int th )
{
	int mid;
	b[th].l		= l; b[th].r = r;
	b[th].flag	= -1;
	if ( l == r )
	{
		b[th].cl = b[th].cr = c[l]; b[th].num = 1; return;
	}
	mid = (b[th].l + b[th].r) / 2;
	build( l, mid, lson ); build( mid + 1, r, rson );
	pushup( th );
}


void update( int l, int r, int color, int th )
{
	int mid;
	if ( b[th].l == l && b[th].r == r )
	{
		b[th].num = 1; b[th].flag = 1; b[th].cl = b[th].cr = color; return;
	}
	pushdown( th );
	mid = (b[th].l + b[th].r) / 2;
	if ( r <= mid )
		update( l, r, color, lson );
	else if ( l > mid )
		update( l, r, color, rson );
	else{ update( l, mid, color, lson ); update( mid + 1, r, color, rson ); }
	pushup( th );
}


int question( int l, int r, int th, int L, int R )
{
	int mid, num;
	if ( b[th].l == L )
		Lc = b[th].cl;
	if ( b[th].r == R )
		Rc = b[th].cr;
	if ( b[th].l == l && b[th].r == r )
	{
		return(b[th].num);
	}
	pushdown( th );
	mid = (b[th].l + b[th].r) / 2;
	if ( r <= mid )
		return(question( l, r, lson, L, R ) );
	else if ( l > mid )
		return(question( l, r, rson, L, R ) );
	else{
		num = question( l, mid, lson, L, R ) + question( mid + 1, r, rson, L, R );
		if ( b[lson].cr == b[rson].cl )
			num--;
		return(num);
	}
}


int solve( int u, int v )
{
	int	f1	= top[u], f2 = top[v];
	int	num	= 0, pre1, pre2;
	pre1 = pre2 = -1;
	while ( f1 != f2 )
	{
		if ( dep[f1] < dep[f2] )
		{
			swap( pre1, pre2 ); swap( f1, f2 ); swap( u, v );
		}
		num += question( p[f1], p[u], 1, p[f1], p[u] );
		if ( pre1 == Rc )
			num--;
		pre1 = Lc; u = fa[f1]; f1 = top[u];
	}
	if ( dep[u] < dep[v] )
	{
		swap( pre1, pre2 ); swap( u, v );
	}
	num += question( p[v], p[u], 1, p[v], p[u] );
	if ( Rc == pre1 )
		num--;
	if ( Lc == pre2 )
		num--;
	return(num);
}


void gengxin( int u, int v, int value )
{
	int f1 = top[u], f2 = top[v];
	while ( f1 != f2 )
	{
		if ( dep[f1] < dep[f2] )
		{
			swap( f1, f2 ); swap( u, v );
		}
		update( p[f1], p[u], value, 1 );
		u	= fa[f1];
		f1	= top[u];
	}
	if ( dep[u] < dep[v] )
		swap( u, v );
	update( p[v], p[u], value, 1 );
}


void add( int u, int v )
{
	tot++;
	e[tot].next	= first[u]; e[tot].to = v;
	first[u]	= tot;
}


int main()
{
	/*
	 * freopen("test.in", "r", stdin);
	 * freopen("test.out", "w", stdout);
	 */

	int	i, j, n, m, u, v, f, g, h;
	char	s[10];
	while ( scanf( "%d%d", &n, &m ) != EOF )
	{
		memset( first, -1, sizeof(first) );
		memset( son, -1, sizeof(son) );
		pos = 0; tot = 0;
		for ( i = 1; i <= n; i++ )
		{
			scanf( "%d", &a[i] );
		}
		for ( i = 1; i <= n - 1; i++ )
		{
			scanf( "%d%d", &u, &v );
			add( u, v ); add( v, u );
		}
		dfs1( 1, 0, 1 ); dfs2( 1, 1 ); build( 1, pos, 1 );
		for ( i = 1; i <= m; i++ )
		{
			scanf( "%s", s );
			if ( s[0] == 'Q' )
			{
				scanf( "%d%d", &f, &g );
				printf( "%d\n", solve( f, g ) );
			}else  {
				scanf( "%d%d%d", &f, &g, &h );
				gengxin( f, g, h );
			}
		}
	}
	return(0);
}


C. 模拟人生:大学生活

#include <bits/stdc++.h>
using namespace std;
const int maxn = 400010;
const int mod = 1000000007;
long long int a[maxn], b[maxn], segtree[maxn << 4];

void build_tree(int l, int r, int now) {
  if (l == r) {
    segtree[now] = a[l] - l;
    return;
  }
  int mid = l + (r - l)/2;
  build_tree(l, mid, now << 1);
  build_tree(mid + 1, r, (now << 1)|1);
  segtree[now] = max(segtree[now << 1], segtree[(now << 1)|1]);
}

long long int query(int L, int R, int l, int r, int now) {
  if (L <= l && R >= r) {
    return segtree[now];
  }
  long long int ans = 0;
  int mid = l + (r - l)/2;
  if (L <= mid) ans = max(ans, query(L, R, l, mid, now << 1));
  if (R > mid) ans = max(ans, query(L, R, mid + 1, r, (now << 1)|1));
  return ans;
}

void update(int l, int r, int tar, int c, int now) {
  if (l == r) {
    segtree[now] = c;
    return;
  }
  int mid = l + (r - l)/2;
  if (tar <= mid) update(l, mid, tar, c, now << 1);
  else update(mid + 1, r, tar, c, (now << 1)|1);
  segtree[now] = max(segtree[now << 1], segtree[(now << 1)|1]);
}

int main()
{
  int n;
  while (scanf("%d", &n) != EOF) {
    memset(segtree, 0, sizeof segtree);
    memset(a, 0, sizeof a);
    memset(b, 0, sizeof b);
    long long int ans = 0;
    for (int i = 1; i <= n; i++) {
      scanf("%lld", &a[i]);
      ans += a[i]%mod;
    }
    for (int i = 1; i <= n; i++) {
      scanf("%lld", &b[i]);
    }

    sort(b + 1, b + n + 1);
    build_tree(1, 2*n, 1);

    for (int i = 1; i <= n; i++) {
      long long int ai = query(b[i], n + i - 1, 1, 2*n, 1);
      ans += ai%mod;
      update(1, 2*n, n + i, ai - n - i, 1);
    }
    printf("%lld\n", ans%mod);
  }

  return 0;
}

D. 奇异人生:暴风雨前夕

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1e5 + 3;
typedef long long int LL;
struct node {
  int l, r;
  LL sum, add;
} segtree[maxn*20];
int root[maxn], n, m, l, r, d, t, x, tot, now;
LL a[maxn] = {0};
char s[10];

int build_tree(int l, int r) {
  int pos = ++tot;
  segtree[pos].sum = segtree[pos].add = 0;
  if (l == r) {
    return pos;
  }
  int mid = l + (r - l)/2;
  segtree[pos].l = build_tree(l, mid);
  segtree[pos].r = build_tree(mid + 1, r);
  return pos;
}

int update(int ind, int L, int R, int d, int l, int r) {
  int pos = ++tot;
  segtree[pos] = segtree[ind];
  segtree[pos].sum += (min(R, r) - max(L, l) + 1)*d;
  if (L <= l && R >= r) {
    segtree[pos].add += d;
    return pos;
  }
  int mid = l + (r - l)/2;
  if (L <= mid) segtree[pos].l = update(segtree[ind].l, L, R, d, l, mid);
  if (R > mid) segtree[pos].r = update(segtree[ind].r, L, R, d, mid + 1, r);
  return pos;
}

LL query(int ind, int L,int R, int l, int r) {
  if (L <= l && R >= r) {
    return segtree[ind].sum;
  }
  LL ans = (min(r, R) - max(L, l) + 1)*segtree[ind].add;
  int mid = l + (r - l)/2;
  if (L <= mid) ans += query(segtree[ind].l, L, R, l, mid);
  if (R > mid) ans += query(segtree[ind].r, L, R, mid + 1, r);
  return ans;
}

int main()
{
  //freopen("test.in", "r", stdin);
  //freopen("test.out", "w", stdout);

  bool flag = 0;
  while (scanf("%d %d", &n, &m) != EOF) {
    if(flag) printf("\n");
    flag = 1;
    memset(segtree, 0, sizeof segtree);
    memset(root, 0, sizeof root);
    tot = now = 0;
    for (int i = 1; i <= n; i++) {
      scanf("%d", &x);
      a[i] = a[i - 1] + x;
    }
    m = 15;
    root[0] = build_tree(1, n);
    for (int i = 0; i < m; i++) {
      scanf("%s", s);
      if(s[0] == 'C') {
        scanf("%d %d %d", &l, &r, &d);
        root[++now] = update(root[now - 1], l, r, d, 1, n);
      } else if (s[0] == 'Q') {
        scanf("%d %d", &l, &r);
        printf("%lld\n", a[r] - a[l - 1] + query(root[now], l, r, 1, n));
      } else if (s[0] == 'H') {
        scanf("%d %d %d", &l, &r, &t);
        printf("%lld\n", a[r] - a[l - 1] + query(root[t], l, r, 1, n));
      } else {
        scanf("%d", &t);
        now = t;
        tot = root[now + 1];
      }

    }
    return 0;
  }

  return 0;
}

E. 水果忍者:狂欢嘉年华

F. 渣渣辉的矿(一)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 240;
struct edge {
  double high, low, x;
  int c;
  bool operator < (const struct edge &a) const {
    return x < a.x;
  }
} edge[maxn << 1];
int n, cnt = 0, tree[maxn << 2];
double a, b, c, d, sum[maxn << 2], p[maxn << 1];

void init() {
  memset(p, 0, sizeof p);
  memset(edge, 0, sizeof edge);
  memset(sum, 0, sizeof sum);
  memset(tree, 0, sizeof tree);
  cnt = 0;
}

void modify(int now, int l, int r) {
  if (tree[now] != 0) sum[now] = p[r + 1] - p[l];
  else if (l == r) sum[now] = 0;
  else sum[now] = sum[now << 1] + sum[(now << 1)|1];
}

void update(int L, int R, int l, int r, int now, int c) {
  if (L <= l && R >= r) {
    tree[now] += c;
    modify(now, l, r);
    return;
  }
  int mid = l + ((r - l) >> 1);
  if (L <= mid) update(L, R, l, mid, now << 1, c);
  if (R > mid) update(L, R, mid + 1, r, (now << 1)|1, c);
  modify(now, l, r);
}

int main()
{
  while (scanf("%d", &n) != EOF && n != 0) {
    init();
    for (int i = 0; i < n; i++) {
      scanf("%lf %lf %lf %lf", &a, &b, &c, &d);
      edge[cnt] = {d, b, a, 1};
      p[cnt++] = b;
      edge[cnt] = {d, b, c, -1};
      p[cnt++] = d;
    }

    sort(edge, edge + cnt);
    sort(p, p + cnt);

    int res = unique(p, p + cnt) - p;
    double ans = 0;
    for (int i = 0; i < cnt - 1; i++) {
      int l = lower_bound(p, p + res, edge[i].low) - p;
      int r = lower_bound(p, p + res, edge[i].high) - p - 1;
      update(l, r, 0, res - 1, 1, edge[i].c);
      ans += sum[1]*(edge[i + 1].x - edge[i].x);
    }

    printf("%.2f\n", ans);
  }


  return 0;
}

G. 渣渣辉的矿(二)

H. 天真的题目

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int b[maxn], tree[maxn << 2], ans[maxn << 2], lazy[maxn << 2], n, m, l, r;
char s[10];

void init() {
  memset(b, 0, sizeof b);
  memset(lazy, 0, sizeof lazy);
  memset(tree, 0, sizeof tree);
  memset(ans, 0, sizeof ans);
}

void build_tree(int l, int r, int now) {
  if (l == r) {
    tree[now] = b[l];
    return;
  }
  int mid = l + ((r - l) >> 1);
  build_tree(l, mid, now << 1);
  build_tree(mid + 1, r, (now << 1)|1);
  tree[now] = min(tree[now << 1], tree[(now << 1)|1]);
}

void pushdown(int now) {
  if (lazy[now] == 0) return;
  lazy[now << 1] += lazy[now];
  lazy[(now << 1)|1] += lazy[now];
  tree[now << 1] -= lazy[now];
  tree[(now << 1)|1] -= lazy[now];
  lazy[now] = 0;
}

void update(int L, int R, int l, int r, int now) {
  if (L <= l && R >= r) {
    tree[now] -= 1;
    if (tree[now] != 0) {
      lazy[now] += 1;
      return;
    } else {
      if (l == r) {
        tree[now] = b[l];
        ans[now] += 1;
        return;
      }
    }
  }
  pushdown(now);
  int mid = l + ((r - l) >> 1);
  if (L <= mid) update(L, R, l, mid, now << 1);
  if (R > mid) update(L, R, mid + 1, r, (now << 1)|1);
  tree[now] = min(tree[now << 1], tree[(now << 1)|1]);
  ans[now] = ans[now << 1] + ans[(now << 1)|1];
}

int query(int L, int R, int l, int r, int now) {
  if (L <= l && R >= r) {
    return ans[now];
  }
  pushdown(now);
  int mid = l + ((r - l) >> 1), res = 0;
  if (L <= mid) res += query(L, R, l, mid, now << 1);
  if (R > mid) res += query(L, R, mid + 1, r, (now << 1)|1);
  return res;
}

int main()
{
  while (scanf("%d%d", &n, &m) != EOF) {
    init();
    for (int i = 1; i <= n; i++) {
      scanf("%d", &b[i]);
    }

    build_tree(1, n, 1);

    for (int i = 0; i < m; i++) {
      scanf("%s %d %d", s, &l, &r);
      if (s[0] == 'a') {
        update(l, r, 1, n, 1);
      } else {
        printf("%d\n", query(l, r, 1, n, 1));
      }
    }
  }

  return 0;
}

I. SUST_ACM 招新啦

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10010;
struct node {
  int l,r,num;
} edge[maxn];
int tree[maxn << 3], q[maxn << 3], cnt, res, ans, n, a, b;
bool vis[maxn << 3];

void pushdown(int now) {
  if (tree[now] != 0) {
    tree[now << 1] = tree[(now << 1)|1] = tree[now];
    tree[now] = 0;
  }
}

void update(int L, int R, int c, int l, int r, int now) {
  if (L <= l && R >= r) {
    tree[now] = c;
    return;
  }
  pushdown(now);
  int mid = l + (r - l)/2;
  if (L <= mid) update(L, R, c, l, mid, now << 1);
  if (R > mid) update(L, R, c, mid + 1, r, (now << 1)|1);
}

void query(int l, int r, int now) {
  if (tree[now] != 0) {
    if (vis[tree[now]] == false) {
      ans++;
      vis[tree[now]] = true;
    }
    return;
  }
  if (l == r) return;
  int mid = l + (r - l)/2;
  query(l, mid, now << 1);
  query(mid + 1, r, (now << 1)|1);
}

int main()
{
  //freopen("test.in", "r", stdin);
  //freopen("test.out", "w", stdout);
  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);
    memset(vis, false, sizeof vis);
    memset(tree, 0, sizeof tree);
    
    cnt = res = 0;
    for (int i = 0; i < n; i++) {
      scanf("%d %d", &a, &b);
      edge[i] = {a, b + 1, i + 1};
      q[cnt++] = a;
      q[cnt++] = b + 1;
    }

    sort(q, q + cnt);
    res = unique(q, q + cnt) - q;

    for (int i = 0; i < n; i++) {
      int l = lower_bound(q, q + res, edge[i].l) - q;
      int r = lower_bound(q, q + res, edge[i].r) - q - 1;
      update(l, r, edge[i].num, 0, res - 1, 1);
    }

    ans = 0;
    query(0, res - 1, 1);
    printf("%d\n",ans);
  }

  return 0;
}

J. 可持久化线段树

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
struct node {
  int l, r;
  long long int sum;
} segtree[maxn << 6];
int a[maxn], root[maxn], n, m, tot;

void init() {
  tot = 0;
  memset(segtree, 0, sizeof segtree);
  memset(a, 0, sizeof a);
  memset(root, 0, sizeof root);
}

int build_tree(int l, int r) {
  int pos = ++tot;
  if (l == r) {
    segtree[pos].sum = a[l];
    return pos;
  }
  int mid = l + (r - l)/2;
  segtree[pos].l = build_tree(l, mid);
  segtree[pos].r = build_tree(mid + 1, r);
  segtree[pos].sum = segtree[segtree[pos].l].sum + segtree[segtree[pos].r].sum;
  return pos;
}

int update(int old, int l, int r, int tar, int c) {
  int pos = ++tot;
  segtree[pos] = segtree[old];
  if (l == r) {
    segtree[pos].sum = c;
    return pos;
  }
  int mid = l + (r - l)/2;
  if (tar <= mid) segtree[pos].l = update(segtree[old].l, l, mid, tar, c);
  else segtree[pos].r = update(segtree[old].r, mid + 1, r, tar, c);
  segtree[pos].sum = segtree[segtree[pos].l].sum + segtree[segtree[pos].r].sum;
  return pos;
}

long long int query(int old, int l, int r, int tar) {
  if (l == r) {
    return segtree[old].sum;
  }
  int mid = l + (r - l)/2;
  if (tar <= mid) return query(segtree[old].l, l, mid, tar);
  else return query(segtree[old].r, mid + 1, r, tar);
}

int main()
{
  while (scanf("%d %d", &n, &m) != EOF) {
    init();
    for (int i = 1; i <= n; i++) {
      scanf("%d", &a[i]);
    }

    root[0] = build_tree(1, n);

    int version, tar, op, value;
    for (int i = 1; i <= m; i++) {
      scanf("%d %d %d", &version, &op, &tar);
      if (op == 1) {
        scanf("%d", &value);
        root[i] = update(root[version], 1, n, tar, value);
      } else {
        root[i] = root[version];
        printf("%lld\n", query(root[version], 1, n, tar));
      }
    }
  }

  return 0;
}

K. 数练泼婚

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
struct node {
  long long int sum, lazy;
} segtree[maxn << 2];
struct EDGE {
  int next, to;
} edge[maxn << 1];
int a[maxn], head[maxn], zson[maxn], fa[maxn], size[maxn], dep[maxn], top[maxn], tid[maxn], rnk[maxn];
int n, m, r, p, cnt, x, y, z, dfsid, op;

void init() {
  memset(segtree, 0, sizeof segtree);
  memset(edge, 0, sizeof edge);
  memset(head, 0, sizeof head);
  memset(a, 0, sizeof a);
  memset(zson, 0, sizeof zson);
  memset(fa, 0, sizeof fa);
  memset(dep, 0, sizeof dep);
  memset(top, 0, sizeof dep);
  memset(tid, 0, sizeof tid);
  memset(rnk, 0, sizeof rnk);
  cnt = dfsid = 0;
}

void add_edge(int x, int y) {
  edge[++cnt].next = head[x];
  edge[cnt].to = y;
  head[x] = cnt;
}

int dfs1(int x, int f, int deep) {
  dep[x] = deep;
  fa[x] = f;
  size[x] = 1;
  for (int i = head[x]; i != 0; i = edge[i].next) {
    int son = edge[i].to;
    if (son == f) continue;
    size[x] += dfs1(son, x, deep + 1);
    if (size[son] > size[zson[x]]) {
      zson[x] = son;
    }
  }
  return size[x];
}

void dfs2(int x, int t) {
  top[x] = t;
  tid[x] = ++dfsid;
  rnk[dfsid] = x;
  if (zson[x] == 0) return;
  dfs2(zson[x], t);
  for (int i = head[x]; i != 0; i = edge[i].next) {
    int son = edge[i].to;
    if (son == fa[x] || son == zson[x]) continue;
    dfs2(son, son);
  }
}

void pushup(int now) {
  segtree[now].sum = segtree[now << 1].sum + segtree[(now << 1)|1].sum;
}

void build_tree(int l, int r, int now) {
  segtree[now].lazy = 0;
  if (l == r) {
    segtree[now].sum = a[rnk[l]];
    return;
  }
  int mid = l + ((r - l) >> 1);
  build_tree(l, mid, now << 1);
  build_tree(mid + 1, r, (now << 1)|1);
  pushup(now);
}

void pushdown(int now, int l, int r) {
  if (segtree[now].lazy == 0) return;
  segtree[now << 1].lazy += segtree[now].lazy;
  segtree[(now << 1)|1].lazy += segtree[now].lazy;
  int mid = l + ((r - l) >> 1);
  segtree[now << 1].sum += segtree[now].lazy*(mid - l + 1);
  segtree[(now << 1)|1].sum += segtree[now].lazy*(r - mid);
  segtree[now].lazy = 0;
}

void update(int L, int R, int l, int r, int c, int now) {
  if (L <= l && R >= r) {
    segtree[now].lazy += c;
    segtree[now].sum += c*(r - l + 1);
    return;
  }
  pushdown(now, l , r);
  int mid = l + ((r - l) >> 1);
  if (L <= mid) update(L, R, l, mid, c, now << 1);
  if (R > mid) update(L, R, mid + 1, r, c, (now << 1)|1);
  pushup(now);
}

long long int query(int L, int R, int l, int r, int now) {
  if (L <= l && R >= r) {
    return segtree[now].sum;
  }
  long long int ans = 0;
  pushdown(now, l, r);
  int mid = l + ((r - l) >> 1);
  if (L <= mid) ans += query(L, R, l, mid, now << 1);
  if (R > mid) ans += query(L, R, mid + 1, r, (now << 1)|1);
  return ans%p;
}

long long int sum(int x, int y) {
  long long int ans = 0;
  int tx = top[x], ty = top[y];
  while (tx != ty) {
    if (dep[tx] >= dep[ty]) {
      ans += query(tid[tx], tid[x], 1, n, 1);
      x = fa[tx];
    } else {
      ans += query(tid[ty], tid[y], 1, n, 1);
      y = fa[ty];
    }
    tx = top[x], ty= top[y];
    ans %= p;
  }

  if (dep[x] >= dep[y]) {
    ans += query(tid[y], tid[x], 1, n, 1);
  } else {
    ans += query(tid[x], tid[y], 1, n, 1);
  }
  return ans%p;
}

void add(int x, int y, int c) {
  int tx = top[x], ty = top[y];
  while (tx != ty) {
    if (dep[tx] >= dep[ty]) {
      update(tid[tx], tid[x], 1, n, c, 1);
      x = fa[tx];
    } else {
      update(tid[ty], tid[y], 1, n, c, 1);
      y = fa[ty];
    }
    tx = top[x], ty= top[y];
  }

  if (dep[x] >= dep[y]) {
    update(tid[y], tid[x], 1, n, c, 1);
  } else {
    update(tid[x], tid[y], 1, n, c, 1);
  }
}

int main()
{
  while(scanf("%d %d %d %d", &n, &m, &r, &p) != EOF) {
    init();
    for (int i = 0; i < n; i++) {
      scanf("%d", &a[i]);
    }
    for (int i = 0; i < n - 1; i++) {
      scanf("%d %d", &x, &y);
      add_edge(x, y);
      add_edge(y, x);
    }

    dfs1(r, -1, 1);
    dfs2(r, r);
    build_tree(1, n, 1);

    for (int i = 0; i < m; i++) {
      scanf("%d", &op);
      if (op == 1) {
        scanf("%d %d %d", &x, &y, &z);
        add(x, y, z);
      } else if (op == 2) {
        scanf("%d %d", &x, &y);
        printf("%lld\n", sum(x, y)%p);
      } else if (op == 3) {
        scanf("%d %d", &x, &z);
        update(tid[x], tid[x] + size[x] - 1, 1, n, z, 1);
      } else {
        scanf("%d", &x);
        printf("%lld\n", query(tid[x], tid[x] + size[x] - 1, 1, n, 1)%p);
      }
    }
  }

  return 0;
}

L. 区间第 K 小

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 10;
struct node {
  int cnt, l, r;
} segtree[maxn << 6];
int tot, a[maxn], b[maxn], n, m, root[maxn];

void pushup(int pos) {
  segtree[pos].cnt = segtree[segtree[pos].l].cnt + segtree[segtree[pos].r].cnt;
}

int build_tree(int l, int r) {
  int pos = ++tot;
  if (l == r) {
    segtree[pos].cnt = 0;
    return pos;
  }
  int mid = l + (r - l)/2;
  segtree[pos].l = build_tree(l, mid);
  segtree[pos].r = build_tree(mid + 1, r);
  pushup(pos);
  return pos;
}

int update(int old, int l, int r, int tar) {
  int pos = ++tot;
  segtree[pos] = segtree[old];
  if (l == r) {
    segtree[pos].cnt += 1;
    return pos;
  }
  int mid = l + (r - l)/2;
  if (tar <= mid) segtree[pos].l = update(segtree[old].l, l, mid, tar);
  else segtree[pos].r = update(segtree[old].r, mid + 1, r, tar);
  pushup(pos);
  return pos;
}

int query(int ri, int le, int k, int l, int r) {
  if (l == r) {
    return l;
  }
  int mid = l + (r - l)/2;
  int cnt = segtree[segtree[ri].l].cnt - segtree[segtree[le].l].cnt;
  if (cnt >= k)
    return query(segtree[ri].l, segtree[le].l, k, l, mid);
  else return query(segtree[ri].r, segtree[le].r, k - cnt, mid + 1, r);
}

int main()
{
  while (scanf("%d %d", &n, &m) != EOF) {
    tot = 0;
    for (int i = 0; i < n; i++) {
      scanf("%d", &a[i]);
      b[i] = a[i];
    }

    sort(b, b + n);
    int res = unique(b, b + n) - b;
    root[0] = build_tree(0, n - 1);

    for (int i = 0; i < n; i++) {
      int tar = lower_bound(b, b + res, a[i]) - b;
      root[i + 1] = update(root[i], 0, n - 1, tar);
    }


    int l, r, k;
    for (int i = 0; i < m; i++) {
      scanf("%d %d %d", &l, &r, &k);
      int idx = query(root[r], root[l - 1], k, 0, n - 1);
      printf("%d\n", b[idx]);
    }

  }


  return 0;
}

M. 区间求和

#include<cstdio>
#include<cstring>
const int maxn = 1e5 + 10;
typedef long long int LL;
LL segtree[maxn << 2], lazy[maxn << 2], a[maxn];

void pushup(int now) {
  segtree[now] = segtree[now << 1] + segtree[(now << 1)|1];
}

void build_tree(int l, int r, int now) {
  if (l == r) {
    segtree[now] = a[l];
    return;
  }
  int mid = l + (r - l)/2;
  build_tree(l, mid, now << 1);
  build_tree(mid + 1, r, (now << 1)|1);
  pushup(now);
}

void pushdown(int now, int l, int r) {
  if (lazy[now] == 0) return;
  lazy[now << 1] += lazy[now];
  lazy[(now << 1)|1] += lazy[now];
  int mid = l + (r - l)/2;
  segtree[now << 1] += lazy[now]*(mid - l + 1);
  segtree[(now << 1)|1] += lazy[now]*(r - mid);
  lazy[now] = 0;
}

void update(int L, int R, int l, int r, int c, int now) {
  if (L <= l && R >= r) {
    lazy[now] += c;
    segtree[now] += c*(r - l + 1);
    return;
  }
  pushdown(now, l , r);
  int mid = l + (r - l)/2;
  if (L <= mid) update(L, R, l, mid, c, now << 1);
  if (R > mid) update(L, R, mid + 1, r, c, (now << 1)|1);
  pushup(now);
}

LL query(int L, int R, int l, int r, int now) {
  if (L <= l && R >= r) {
    return segtree[now];
  }
  pushdown(now, l, r);
  int mid = l + (r - l)/2;
  LL ans = 0;
  if (L <= mid) ans += query(L, R, l, mid, now << 1);
  if (R > mid) ans += query(L, R, mid + 1, r, (now << 1)|1);
  pushup(now);
  return ans;
}

int main()
{
  int n, m;
  while (scanf("%d %d", &n, &m) != EOF) {
    memset(segtree, 0, sizeof segtree);
    memset(lazy, 0, sizeof lazy);

    for (int i = 1; i <= n; i++) {
      scanf("%lld", &a[i]);
    }

    build_tree(1, n, 1);

    char s[10];
    int x, y, z;
    for (int i = 0; i < m; i++) {
      scanf("%s", s);
      if (s[0] == 'C') {
        scanf("%d %d %d", &x, &y, &z);
        update(x, y, 1, n, z, 1);
      } else {
        scanf("%d %d", &x, &y);
        printf("%lld\n", query(x, y, 1, n, 1));
      }
    }
  }

  return 0;
}

N. 区间最大公约数

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
long long int a[maxn], segtree[maxn << 2];
int n, q, T;

long long int gcd(long long int a, long long int b) {
  return b == 0?a:gcd(b,a%b);
}

void update(int now) {
  segtree[now] = gcd(segtree[now << 1], segtree[(now << 1)|1]);
}

void build_tree(int l = 1, int r = n, int now = 1) {
  if (l == r) {
    segtree[now] = a[l];
    return;
  }
  int mid = l + (r - l)/2;
  build_tree(l, mid, now << 1);
  build_tree(mid + 1, r, (now << 1)|1);
  update(now);
}

long long int query(int L, int R, int now = 1, int l = 1, int r = n) {
  if (L <= l && R >= r) {
    return segtree[now];
  }
  long long int ans = 0;
  int mid = l + (r - l)/2;
  if (L <= mid) ans = gcd(ans,query(L, R, now << 1, l, mid));
  if (R > mid) ans = gcd(ans,query(L, R, (now << 1)|1, mid + 1, r));
  return ans;
}

int main()
{
  //freopen("test.in", "r", stdin);
  //freopen("test.out", "w", stdout);
  scanf("%d", &T);
  for (int ca = 1; ca <= T; ca++) {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
      scanf("%lld", &a[i]);
    }
    build_tree();
    map <long long int,long long int> mp;

    for (int i = 1; i <= n; i++) {
      int l = i, r = n, mid, vs, ans, pp;
      while (1) {
        ans = l;
        pp = l;
        vs = query(i, l);
       if(vs == 1) mp[vs] += 1LL*(n - l + 1);
        while (l <= r) {
          mid = (l + r) >> 1;
          if (query(i, mid) < vs) r = mid - 1;
          else ans = mid, l = mid + 1;
        mp[vs] += 1LL*(ans - pp + 1);
        l = ans + 1, r = n;
        if (l > r) break;
      }
    }

    printf("Case #%d:\n", ca);
    scanf("%d", &q);
    int l,r;
    for (int i = 0;i < q; i++) {
      scanf("%d %d", &l, &r);
      long long int ans1 = query(l, r);
      printf("%lld %lld\n", ans1, mp[ans1]);
    }

  }

  return 0;
}

O. 很高兴你来了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e6 + 10;
unsigned int a[maxn], f[3*maxn], segtree[maxn << 2];
unsigned int x, y, z;
int n, m;

void init(){
  memset(a, 0, sizeof a);
  memset(f, 0, sizeof f);
  memset(segtree, 0, sizeof segtree);
}

unsigned int rng61() {
  x = x^(x << 11);
  x = x^(x >> 4);
  x = x^(x << 5);
  x = x^(x >> 14);
  unsigned int w = x^(y^z);
  x = y;
  y = z;
  z = w;
  return z;
}

void update(int L, int R,unsigned int l, unsigned int r, unsigned int v, int now) {
  if (L <= l && R >= r) {
    if (v > segtree[now]) segtree[now] = v;
    return;
  }
  int mid = l + (r - l)/2;
  if (L <= mid) update(L, R, l, mid, v, now << 1);
  if (R > mid) update(L, R, mid + 1, r, v, (now << 1)|1);
  return;
}

void pushdown(int now) {
  if (segtree[now] > segtree[now << 1]) segtree[now << 1] = segtree[now];
  if (segtree[now] > segtree[(now << 1)|1]) segtree[(now << 1)|1] = segtree[now];
}

unsigned int query(int l, int r, int now) {
  if (l == r) {
    return (unsigned int)l*segtree[now];
  }
  pushdown(now);
  int mid = l + (r - l)/2;
  unsigned int ans = 0;
  ans ^= query(l, mid, now << 1);
  ans ^= query(mid + 1, r, (now << 1)|1);
  return ans;
}

int main()
{
  int T, mod = pow(2, 30);
  scanf("%d", &T);
  while (T--) {
    scanf("%d %d %u %u %u", &n, &m, &x, &y, &z);
    for (int i = 1;i <= 3*m; i++) {
      f[i] = rng61();
    }
    unsigned int l, r, v;
    for (int i = 1;i <= n; i++) {
      l = min(f[3*i - 2]%n + 1, f[3*i - 1]%n + 1);
      r = max(f[3*i - 2]%n + 1, f[3*i - 1]%n + 1);
      v = f[3*i]%mod;
      update(l, r, 1, n, v, 1);
    }

    printf("%u\n", query(1, n, 1));

  }

  return 0;
}

P. 决战圆锥曲线

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
 
typedef long long LL;
 
inline LL gint() {
    char c = getchar();
    int f = 1;
    while(c < '0'||c > '9') {
        if(c == '-') {
            f = -1;
        }
        c = getchar();
    }
    LL a = c - '0';
    while ((c = getchar()) >= '0' && c <= '9') {
        a = a * 10 + c - '0';
    }
    return a * f;
}
 
struct BufferReader {
    LL x;
    BufferReader(LL x = 0):x(x) {}
    LL nextInt() {
        x = (x * 100000005 + 20180821) % 998244353;
        return x / 100;
    }
};
 
 
const int maxn = 100010;
#define lson s << 1
#define rson (s << 1)|1
#define linfo s << 1,l,mid
#define rinfo (s << 1)|1, mid + 1, r
 
int miny[maxn << 2], maxy[maxn << 2];
bool inv[maxn << 2];
 
inline void up(int s) {
    miny[s] = min(miny[lson], miny[rson]);
    maxy[s] = max(maxy[lson], maxy[rson]);
}
 
inline void inverse(int s) {
    inv[s] ^= 1;
    miny[s] = 100000 - miny[s];
    maxy[s] = 100000 - maxy[s];
    swap(miny[s], maxy[s]);
}
 
inline void down(int s) {
    if(inv[s]) {
        inverse(lson);
        inverse(rson);
        inv[s] = 0;
    }
}
 
int A[maxn];
 
void build(int s, int l, int r) {
    if(l == r) {
        miny[s] = maxy[s] = A[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(linfo);
    build(rinfo);
    up(s);
}
 
LL a, b, c, ans;
int ql, qr;
 
void change(int s, int l, int r) {
    if(l == r) {
        miny[s] = maxy[s] = qr;
        return;
    }
    down(s);
    int mid = (l + r) >> 1;
    if(ql <= mid) {
        change(linfo);
    } else {
        change(rinfo);
    }
    up(s);
}
 
void update(int s, int l, int r) {
    if(ql <= l && r <= qr) {
        inverse(s);
        return;
    }
    down(s);
    int mid = (l + r) >> 1;
    if(ql <= mid) {
        update(linfo);
    }
    if(mid < qr) {
        update(rinfo);
    }
    up(s);
}
 
inline LL calc(LL x,LL y) {
    return a * x + b * y + c * x * y;
}
 
void query(int s, int l, int r) {
    if(l == r) {
        ans = max(ans, calc(l, maxy[s]));
        return;
    }
    if(calc(min(r, qr), maxy[s]) <= ans) {
        return;
    }
    down(s);
    int mid = (l + r) >> 1;
    if(qr <= mid) {
        return query(linfo);
    }
    if(mid < ql) {
        return query(rinfo);
    }
    LL lans = calc(mid, maxy[lson]);
    LL rans = calc(min(qr, r), maxy[rson]);
    if(lans < rans) {
        query(rinfo);
        query(linfo);
    } else {
        query(linfo);
        query(rinfo);
    }
}
 
int n, m;
 
int main() {
  //freopen("test.in", "r", stdin);
  //freopen("test.out", "w", stdout);
    n = gint();
    m = gint();
    BufferReader cin(gint());
    for (int i = 1; i <= n; i++) {
        A[i] = cin.nextInt() % 100001;
    }
    build(1, 1, n);
    while (m--) {
        char op = getchar();
        while(!isalpha(op)) {
            op = getchar();
        }
        if(op == 'C') {
            ql = cin.nextInt() % n + 1;
            qr = cin.nextInt() % 100001;
            change(1, 1, n);
        } else if(op == 'R') {
            ql = cin.nextInt() % n + 1;
            qr = cin.nextInt() % n + 1;
            if(ql > qr) swap(ql, qr);
            update(1, 1, n);
        } else {
            a = gint(), b = gint(), c = gint();
            ql = cin.nextInt() % n + 1;
            qr = cin.nextInt() % n + 1;
            if(ql > qr) swap(ql, qr);
            ans = 0;
            query(1, 1, n);
            printf("%lld\n", ans);
        }
    }
    return 0;
}

Q. 敌兵布阵

#include <cstdio>
const int maxn = 200000;
long long int segtree[maxn << 2], a[maxn];
 
void pushup(int now) {
  segtree[now] = segtree[now << 1] + segtree[(now << 1)|1];
}
 
void build_tree(int l, int r, int now) {
  if (l == r) {
    segtree[now] = a[l];
    return;
  }
  int mid = l + (r - l)/2;
  build_tree(l, mid, now << 1);
  build_tree(mid + 1, r, (now << 1)|1);
  pushup(now);
}
 
void update(int l, int r, int now, int tar, int c) {
  if (l == r) {
    segtree[now] += c;
    return;
  }
  int mid = l + (r - l)/2;
  if (tar <= mid) update(l, mid, now << 1, tar, c);
  else update(mid + 1, r, (now << 1)|1, tar, c);
  pushup(now);
}
 
long long int query(int L, int R, int l, int r, int now) {
  if(L <= l && R >= r){
    return segtree[now];
  }
  long long int ans = 0;
  int mid = l + (r - l)/2;
  if (L <= mid) ans += query(L, R, l, mid, now << 1);
  if (R > mid) ans += query(L, R, mid + 1, r, (now << 1)|1);
  return ans;
}
 
int main()
{
  int T, n, x, y, ca = 0;
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
      scanf("%lld", &a[i]);
    }
 
    build_tree(1, n, 1);
    printf("Case %d:\n", ++ca);
 
    char s[10];
    while(scanf("%s", s), s[0] != 'E') {
      scanf("%d %d", &x, &y);
      if (s[0] == 'Q') {
        printf("%lld\n", query(x, y, 1, n, 1));
      } else if (s[0] == 'S') {
        update(1, n, 1, x, -y);
      } else {
        update(1, n, 1, x, y);
      }
    }
 
  }
 
  return 0;
}
发布了79 篇原创文章 · 获赞 56 · 访问量 50万+

猜你喜欢

转载自blog.csdn.net/qq_40861916/article/details/95592352
今日推荐