kuangbin 线段树题解打印

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <vector>

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>

#define inf 0x3f3f3f3f
#define cha 1e-6
#define ll long long
using namespace std;
const int maxn = 1e5 + 6;
ll node[270000],lazy[270000];
ll a[100005];
inline void lazyuild(ll s ,ll t,ll p ){
    
    
    if(s==t){
    
    
        node[p]=a[s];
        return ;
    }
    ll m=(s+t)/2;
    lazyuild(s,m,p*2), lazyuild(m+1,t,p*2+1);
    node[p]=node[p*2]+node[(2*p)+1];
}

inline ll getsum(ll l,ll r,ll s ,ll t,ll p){
    
    
    if(l<=s&&t<=r)
        return node[p];
    ll m=(s+t)/2,sum=0;
    if(lazy[p]){
    
    
        node[p*2]+=lazy[p]*(m-s+1), node[p*2+1]+=lazy[p]*(t-m);
        lazy[p*2]+=lazy[p],lazy[p*2+1]+=lazy[p];
        
    }
    lazy[p]=0;
    if(l<=m) sum+=getsum(l,r,s,m,p*2);
    if(r>m) sum+=getsum(l,r,m+1,t,p*2+1);
    return sum;
}

void updateplus(ll l, ll r, ll c, ll s, ll t, ll p) {
    
    
  if (l <= s && t <= r) {
    
    
    node[p] += (t - s + 1) * c, lazy[p] += c;
    return;
  }
  ll m = (s + t)/2;
  if (lazy[p])
    node[p*2] += lazy[p]*(m-s+1), node[(p *2)+1] += lazy[p] * (t - m),
        lazy[p *2] += lazy[p], lazy[(p*2)+1] += lazy[p];
  lazy[p] = 0;
  if (l <= m) updateplus(l, r, c, s, m, p *2);
  if (r > m) updateplus(l, r, c, m + 1, t, (p *2)+1);
  node[p] = node[p*2] + node[p*2+1];
}

inline void updatereplace(ll l,ll r,ll c,ll s,ll t ,ll p){
    
    
    if(l<=s&&t<=r){
    
    
        node[p]=(t-s+1)*c,lazy[p]=c;
        return ;
    }
    ll m = (s + t)/2;
    if (lazy[p])
        node[p*2] += lazy[p]*(m-s+1), node[(p *2)+1] += lazy[p] * (t - m),
        lazy[p *2] += lazy[p], lazy[(p*2)+1] += lazy[p];
    lazy[p] = 0;
    if (l <= m) updateplus(l, r, c, s, m, p *2);
    if (r > m) updateplus(l, r, c, m + 1, t, (p *2)+1);
    node[p] = node[p*2] + node[p*2+1];
}
int main()
{
    
    
    ios::sync_with_stdio(false);
    ll n,m;
    cin>>n>>m;
    for(ll i=1;i<=n;i++)
        cin>>a[i];
    lazyuild(1,n,1);
    while(m--){
    
    
        ll i1,i2,i3;
        cin>>i1>>i2>>i3;
        if(i1==2) cout<<getsum(i2,i3,1,n,1)<<endl;
        else{
    
    
            ll i4;
            cin>>i4;
            updateplus(i2,i3,i4,1,n,1);
        }
    }
    system("pause");
    return 0;
}

区间乘法

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <vector>

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>

#define inf 0x3f3f3f3f
#define cha 1e-6
#define ll long long
using namespace std;
const int maxn = 1e5 + 6;
ll node[400005],lazy[400005],mul[400005];
ll a[100005];
ll mod;
ll read() {
    
    
  ll w = 1, q = 0;
  char ch = ' ';
  while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
  if (ch == '-') w = -1, ch = getchar();
  while (ch >= '0' && ch <= '9') q = (ll)q * 10 + ch - '0', ch = getchar();
  return (ll)w * q;
}
int n, m;
void up(ll i) {
    
     node[i] = (node[(i << 1)] + node[(i << 1) | 1]) % mod; }
void pd(ll i, ll s, ll t) {
    
    
  ll l = (i << 1), r = (i << 1) | 1, mid = (s + t) >> 1;
  if (mul[i] != 1) {
    
    
      mul[l] *= mul[i];mul[l] %= mod;
      mul[r] *= mul[i];mul[r] %= mod;
      lazy[l] *= mul[i];lazy[l] %= mod;
      lazy[r] *= mul[i];lazy[r] %= mod;
      node[l] *= mul[i];node[l] %= mod;
      node[r] *= mul[i];node[r] %= mod;
      mul[i] = 1;
  }
  if (lazy[i]) {
    
    
      node[l] += lazy[i] * (mid - s + 1);node[l] %= mod;
      node[r] += lazy[i] * (t - mid);node[r] %= mod;
      lazy[l] += lazy[i];lazy[l] %= mod;
      lazy[r] += lazy[i];lazy[r] %= mod;
      lazy[i] = 0;
  }
  return;
}
void build(ll s, ll t, ll i) {
    
    
  mul[i] = 1;
  if (s == t) {
    
    
    node[i] = a[s];
    return;
  }
  ll mid = (s + t) >> 1;
  build(s, mid, i << 1);
  build(mid + 1, t, (i << 1) | 1);
  up(i);
}
inline void updatemul(ll l, ll r, ll s, ll t, ll p, ll z) {
    
    
    ll mid = (s + t) >> 1;
    if (l <= s && t <= r) {
    
    
        mul[p] *= z;mul[p] %= mod;
        lazy[p] *= z;lazy[p] %= mod;
        node[p] *= z;node[p] %= mod;
        return;
    }
    pd(p, s, t);
    if (mid >= l) updatemul(l, r, s, mid, (p << 1), z);
    if (mid + 1 <= r) updatemul(l, r, mid + 1, t, (p << 1) | 1, z);
    up(p);
}
inline void updateplus(ll l, ll r, ll s, ll t, ll p, ll z) {
    
    
    ll mid = (s + t) >> 1;
    if (l <= s && t <= r) {
    
    
        node[p] += z * (t - s + 1);node[p] %= mod;
        lazy[p] += z;lazy[p] %= mod;
        return;
    }
    pd(p, s, t);
    if (mid >= l) updateplus(l, r, s, mid, (p << 1), z);
    if (mid + 1 <= r) updateplus(l, r, mid + 1, t, (p << 1) | 1, z);
    up(p);
}
inline ll getsum(ll l, ll r, ll s, ll t, ll p) {
    
    
    ll mid = (s + t) >> 1;
    ll sum = 0;
    if (l <= s && t <= r) return node[p];
    pd(p, s, t);
    if (mid >= l) sum += getsum(l, r, s, mid, (p << 1));
    sum %= mod;
    if (mid + 1 <= r) sum += getsum(l, r, mid + 1, t, (p << 1) | 1);
    return sum % mod;
}
int  main() {
    
    
  ll i, j, x, y, bh;
  ll z;
  n = read();
  m = read();
  mod = read();
  for (i = 1; i <= n; i++) a[i] = read();
  build(1, n, 1);
  for (i = 1; i <= m; i++) {
    
    
    bh = read();
    if (bh == 1) {
    
    
        x = read();
        y = read();
        z = read();
        updatemul(x, y, 1, n, 1, z);
    } else if (bh == 2) {
    
    
        x = read();
        y = read();
        z = read();
        updateplus(x, y, 1, n, 1, z);
    } else if (bh == 3) {
    
    
        x = read();
        y = read();
        printf("%lld\n", getsum(x, y, 1, n, 1));
    }
  }
  system("pause");
  return 0;
}

输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 2005;
struct Line {
    
    
	int st; //代表1 -1 2种状态 
	double s, e, x;
	bool operator < (const Line & w) const {
    
    
		return x < w.x; //按照x小的排在前面 
	}
} line[N];
struct Node {
    
    
	int cnt, lazy; //代表被包含的次数 
	double len; //这个区间被包含的长度 
} tr[N << 2]; 
int n, cnt, t; // cnt代表离散化后数组里面元素的个数 
double fy[N], x11, x22, y11, y22; 
void build(int id, int l, int r) {
    
    
	tr[id].cnt = tr[id].lazy = tr[id].len = 0;
	if (l == r) return;
	int mid = (l + r) >> 1;
	build(id << 1, l, mid);
	build(id << 1 | 1, mid + 1, r);
}
void pushup(int id, int l, int r) {
    
    
	if (tr[id].cnt >= 2) {
    
     // 代表id这个区间被覆盖了  
		tr[id].len = fy[r + 1] - fy[l]; //因为一个点代表的是一个区间 那r这个点的区间 就是[fy[r], fy[r + 1]]这段长度 
	} else if (l != r) {
    
      //如果这整个区间没有被包含 那么就由儿子区间组成 
		tr[id].len = tr[id << 1].len + tr[id << 1 | 1].len; 
	} else tr[id].len = 0; //叶子结点  
}
void pushdown(int id, int l, int r) {
    
    
	if (tr[id].lazy == 0) return;
	tr[id << 1].cnt += tr[id].lazy;
	tr[id << 1 | 1].cnt += tr[id].lazy;
	tr[id << 1].lazy += tr[id].lazy;
	tr[id << 1 | 1].lazy += tr[id].lazy;
	tr[id].lazy = 0;
}
void query(int id, int l, int r) {
    
    
	if (l == r) {
    
    
		pushup(id, l, r);
		return; 
	}
	pushdown(id, l, r); //查询的时候将所有层次的标记进行下放  
	int mid = (l + r) >> 1;
	query(id << 1, l, mid);
	query(id << 1 | 1, mid + 1, r);
	pushup(id, l, r);
}
void update(int id, int l, int r, int x, int y, int d) {
    
    
	if (x <= l && r <= y) {
    
    
		tr[id].cnt += d;
		tr[id].lazy += d;
		pushup(id, l, r); //及时更新这段区间 因为父亲区间可能需要用到我这个区间的len 
		return;
	}
	int mid = (l + r) >> 1;
	pushdown(id, l, r); 
	if (x <= mid) update(id << 1, l, mid, x, y, d);
	if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, d);
	pushup(id, l, r); 
} 
int find(double y) {
    
    
	return lower_bound(fy + 1, fy + 1 + cnt, y) - fy; 
}
int main() {
    
    
	scanf("%d", &t); 
	while (t--) {
    
    
		scanf("%d", &n);
		for (int i = 1, j = 1; i <= n; i++) {
    
    
			scanf("%lf%lf%lf%lf", &x11, &y11, &x22, &y22);
			line[j].s = y11, line[j].e = y22, line[j].x = x11, line[j].st = 1, fy[j++] = y11;
			line[j].s = y11, line[j].e = y22, line[j].x = x22, line[j].st = -1, fy[j++] = y22;
		}
		sort(line + 1, line + 1 + 2 * n);
		sort(fy + 1, fy + 1 + 2 * n);
		cnt = unique(fy + 1, fy + 1 + 2 * n) - fy - 1; //获取去重后元素的个数
		build(1, 1, cnt - 1); //一个点代表的是一个区间, 一共有cnt个点 所以只有cnt-1个区间
		double ans = 0;
		for (int i = 1; i <= 2 * n; i++) {
    
    
			query(1, 1, cnt - 1); //先查询一次才能够使用1这个节点的区间 
			ans += tr[1].len * (line[i].x - line[i - 1].x);
			update(1, 1, cnt - 1, find(line[i].s), find(line[i].e) - 1, line[i].st); //这里-1是因为每个点代表的是一个区间 我们不能包含e那个点所代表的区间 
		} 
		printf("%.2lf\n", ans); 
	}
	return 0;
}

区间最长

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<cstdio>
#include<vector>
#include<set>
#include<cstring>
#include<cstdlib>
#include<time.h>
#include<stack>
using namespace std;
const int maxn=550000;
int  node[maxn];
void build(int l,int r,int index){
    
    
	if(l==r) scanf("%d",&node[index]);
	else{
    
    
		int mid=(r+l)>>1;
		build(l,mid,index<<1);
		build(mid+1,r,index<<1|1);//左
		node[index]=max(node[index<<1],node[index<<1|1]);//右
	}
}
int query(int x,int y,int l,int r,int index){
    
    
	if(x<=l&&y>=r) return node[index];
	else{
    
    
		int mid=(l+r)>>1,mx=0;
		if(x<=mid) mx=max(mx,query(x,y,l,mid,index<<1));//左
		if(y>mid) mx=max(mx,query(x,y,mid+1,r,index<<1|1));//右
		return mx;
	}
}
void update(int p,int v,int l,int r,int index){
    
    
	if(l==r) node[index]=v;
	else{
    
    
		 int mid=(l+r)>>1;
        if(p<=mid) update(p,v,l,mid,index<<1);
        else update(p,v,mid+1,r,index<<1|1);
        node[index]=max(node[index<<1],node[index<<1|1]);
	}
}
int main(){
    
    
	int n,m,x,y;
	char s[2];
		while(scanf("%d%d",&n,&m)!=EOF){
    
    
		build(1,n,1);
		while(m--){
    
    
			scanf("%s%d%d",s,&x,&y);
			if(s[0]=='Q')printf("%d\n",query(x,y,1,n,1));
			else update(x,y,1,n,1);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45891413/article/details/111713150
今日推荐