[模板计划] 数据结构

数据结构


队列

链表与邻接表

Hash

字符串

KMP算法

Trie

二叉堆

并查集

树状数组

线段树

  • 区间加(懒标记)
#include<cstdlib>
#include<cstring>
#include<iostream>
#define ll long long
using namespace std;
const int MAX = 100000 + 5;
inline int read(){
    int f = 1, x = 0;char ch;
    do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');
    do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
    return f*x;
}
int n, m, a[MAX];

struct sakura {
    int l, r;
    int dat;
    ll sum;
    ll add;
}sak[4*MAX];

inline void build(int p, int l, int r) {
    sak[p].l = l, sak[p].r = r;
    if (l == r) {
        sak[p].dat = a[l], sak[p].sum = a[l];
        return;
    }
    int mid = (l + r) / 2;
    build(2*p, l, mid);
    build(2*p + 1, mid + 1, r);
    sak[p].sum = sak[2*p].sum + sak[2*p + 1].sum;
}

inline void pushdown(int p) {
    if (sak[p].add) {
        sak[2*p].sum += sak[p].add*(sak[2*p].r - sak[2*p].l+1);
        sak[2*p+1].sum += sak[p].add*(sak[2*p+1].r - sak[2*p+1].l+1);
        sak[2*p].add += sak[p].add;
        sak[2*p+1].add += sak[p].add;
        sak[p].add = 0; 
    }
}

inline void change(int p, int l, int r, int d) {
    if (l <= sak[p].l && r >= sak[p].r) {
        sak[p].sum += (ll)d*(sak[p].r - sak[p].l+1);
        sak[p].add += d;
        return;
    }
    pushdown(p);
    int mid = (sak[p].l + sak[p].r) / 2;
    if (l <= mid) change(2*p, l, r, d);
    if (r > mid) change(2*p + 1, l, r, d);
    sak[p].sum = sak[2*p].sum + sak[2*p + 1].sum;	
}

inline ll ask(int p, int l, int r) {
    if (l <= sak[p].l && r >= sak[p].r) {
        return sak[p].sum;
    }
    pushdown(p);
    ll val = 0;
    int mid = (sak[p].l + sak[p].r) / 2;
    if (l <= mid) val += ask(2*p, l, r);
    if (r > mid) val += ask(2*p + 1, l, r);
    return val;	
} 

int main(){
    n = read(), m = read();
    for (int i = 1;i <= n; ++i) a[i] = read();
    build(1, 1, n);
    for (int i = 1;i <= m; ++i) {
    	int opt = read();
    	switch (opt) {
    		case 1:{
    			int x = read(), y = read(), k = read();
    			change(1, x, y, k);
    			break;
    		}
    		case 2:{
    			int x = read(), y = read();
    			printf("%lld\n", ask(1, x, y));
    			break;
    		}
    	}
    }
    return 0;
}
  • 区间加,区间乘(懒标记优先级判断)
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug() puts("FBI WARNING!")
#define ll long long
using namespace std;
const int MAX = 100000 + 5;
inline int read(){
    int f = 1, x = 0;char ch;
    do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');
    do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
    return f*x;
}
int n, m, mod, a[MAX];

struct sakura {
    int l, r;
    ll sum; ll add; ll mul;
    sakura() {
    	l = 0, r = 0, sum = 0, add = 0, mul = 1;
    }
}sak[10*MAX];

inline void build(int p, int l, int r) {
    sak[p].l = l, sak[p].r = r;
    if (l == r) {
        sak[p].sum = a[l]%mod;
        return;
    }
    int mid = (l + r) / 2;
    build(2*p, l, mid);
    build(2*p + 1, mid + 1, r);
    sak[p].sum = (sak[2*p].sum + sak[2*p + 1].sum)%mod;
}

inline void pushdown(int p) {
    sak[2*p].sum = (sak[2*p].sum*sak[p].mul + sak[p].add*(sak[2*p].r - sak[2*p].l+1))%mod;
    sak[2*p+1].sum = (sak[2*p+1].sum*sak[p].mul + sak[p].add*(sak[2*p+1].r - sak[2*p+1].l+1))%mod;
    sak[2*p].add = (sak[p].add + sak[2*p].add*sak[p].mul)%mod;
    sak[2*p+1].add = (sak[p].add + sak[2*p+1].add*sak[p].mul)%mod;
    sak[2*p].mul = (sak[2*p].mul*sak[p].mul)%mod;
    sak[2*p+1].mul = (sak[2*p+1].mul*sak[p].mul)%mod;
    sak[p].add = 0; 
    sak[p].mul = 1;
}

inline void change(int p, int l, int r, ll d) {
    if (l <= sak[p].l && r >= sak[p].r) {
        sak[p].sum = (sak[p].sum + d*(sak[p].r - sak[p].l+1))%mod;
        sak[p].add = (sak[p].add + d)%mod;
        return;
    }
    pushdown(p);    
    int mid = (sak[p].l + sak[p].r) / 2;
    if (l <= mid) change(2*p, l, r, d);
    if (r > mid) change(2*p + 1, l, r, d);
    sak[p].sum = (sak[2*p].sum + sak[2*p + 1].sum)%mod;	
}

inline void mull(int p, int l, int r, int d) {
   	
    if (l <= sak[p].l && r >= sak[p].r) {
        sak[p].mul = (sak[p].mul * d)%mod;
        sak[p].add = (sak[p].add * d)%mod;
        sak[p].sum = (sak[p].sum * d)%mod;      
        return;
    }
    pushdown(p);       
    int mid = (sak[p].l + sak[p].r) / 2;
    if (l <= mid) mull(2*p, l, r, d);
    if (r > mid) mull(2*p + 1, l, r, d);
    sak[p].sum = (sak[2*p].sum + sak[2*p + 1].sum)%mod;	
}

inline ll ask(int p, int l, int r) {
    if (l <= sak[p].l && r >= sak[p].r) {
        return sak[p].sum%mod;
    }
    pushdown(p);    
    ll val = 0;
    int mid = (sak[p].l + sak[p].r) / 2;
    if (l <= mid) val = (val + ask(2*p, l, r))%mod;
    if (r > mid) val = (val + ask(2*p + 1, l, r))%mod;
    return val;
} 

int main(){
    n = read(), m = read(), mod = read();
    for (int i = 1;i <= n; ++i) a[i] = read(); 
    build(1, 1, n);
    for (int i = 1;i <= m; ++i) {
    	int opt = read();
    	switch (opt) {
    		case 1:{
    			int x = read(), y = read(), k = read();
    			mull(1, x, y, k);
    			break;
    		} 
    		case 2:{
    			int x = read(), y = read(), k = read();
    			change(1, x, y, k);
    			break;
    		}
    		case 3:{
    			int x = read(), y = read();
    			printf("%lld\n", ask(1, x, y));
    			break;
    		}
    	}
    }
    return 0;
}
  • 扫描线
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug() puts("FBI WARNING!")
#define ll long long
using namespace std;
const int MAX = 1000 + 5;

int n, tot, cnts[4*MAX];
double x1, x2, y, y2, raw[2*MAX], ans;

inline int read(){
	char ch = getchar();
	int res = 0, f = 1;
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar(); }
	while(isdigit(ch)) res = (res<<3) + (res<<1) + (ch^48), ch = getchar();
	return res*f;
}
inline void write(ll x){if(x > 9) write(x/10); putchar(x%10+48); return;}

struct sakura{ double x, y1, y2; int k; }sak[MAX]; int cnt;
struct Segment{ double l, r; double sum; }tree[4*MAX];

inline void push_up(int p) {
	if (cnts[p] > 0) { tree[p].sum = tree[p].r - tree[p].l; }
	else { tree[p].sum = tree[p << 1].sum + tree[(p << 1) + 1].sum; }
}

inline void build(int p, int l, int r) {
	if(r-l == 1) {
        tree[p].l = raw[l], tree[p].r = raw[r], tree[p].sum = 0;
    	return;
	}
	tree[p].l = raw[l], tree[p].r = raw[r];
    int mid = (l + r) >> 1;
    build(2*p, l, mid);
    build(2*p + 1, mid, r);	
    push_up(p);
    return ;
}

inline void change(int p, double y1, double y2, int flag) {
	if (tree[p].l == y1 && tree[p].r == y2) {
		cnts[p] += flag;
		push_up(p);
		return;
	}
	if (tree[p << 1].r > y1) {
		change(p << 1, y1, min(y2, tree[p << 1].r), flag);
	}
	if (tree[(p << 1) + 1].l < y2) {
		change((p << 1) + 1, max(tree[(p << 1) + 1].l, y1), y2, flag);
	}
	push_up(p);
}

inline void clean() {
	memset(cnts, 0, sizeof (cnts));
	cnt = 0;
	ans = 0;
}

inline void add() {
	sak[cnt].x = x1, sak[cnt].y1 = y, sak[cnt].y2 = y2, sak[cnt].k = 1;
	++cnt;
	sak[cnt].x = x2, sak[cnt].y1 = y, sak[cnt].y2 = y2, sak[cnt].k = -1;
	++cnt;
}

inline bool cmp(const sakura &a, const sakura &b) { return a.x < b.x; }

int main(){
	while (n = read()) {
		if (n == 0) break;
		clean();
		for (int i = 1;i <= n; ++i) {
			scanf("%lf%lf%lf%lf", &x1, &y, &x2, &y2);
			add();
			raw[i] = y;
			raw[i+n] = y2;
		}
		sort(sak, sak+2*n, cmp);
		sort(raw+1, raw+(2*n+1));
		build(1, 1, n << 1);
		change(1, sak[0].y1, sak[0].y2, sak[0].k);
		for (int i = 1;i < (n << 1); ++i) {
			ans += (sak[i].x - sak[i-1].x) * tree[1].sum;
			change(1, sak[i].y1, sak[i].y2, sak[i].k);
		}
		printf("Test case #%d\nTotal explored area: %.2lf\n\n", ++tot, ans);
	}
	return 0;
}

分块

点分治

BFS

离线分治算法

可持续化数据结构

posted @ 2019-05-27 09:39  SilentEAG  阅读(151)  评论(0)    收藏  举报