数据结构以及图论补充

线段树:
一、单点修改,区间查询

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
int n, Q;
int a[maxn];
int suma[maxn];
typedef struct
{
	int l, r;
	int sum;
}T;
T t[maxn << 1];

inline void build(int rt, int l, int r)
{
	t[rt].l = l;
	t[rt].r = r;
	if (l == r)
	{
		t[rt].sum = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid + 1, r);
	t[rt].sum = t[rt << 1].sum + t[rt << 1 | 1].sum;
}
inline int interval_add(int rt, int l, int r)
{
	if (t[rt].l >= l && t[rt].r <= r)return t[rt].sum;
	if (t[rt].l > r || t[rt].r < l)return 0;
	int temp = 0;
	if (t[rt << 1].r >= l)temp += interval_add(rt << 1, l, r);
	if (t[rt << 1 | 1].l <= r)temp += interval_add(rt << 1 | 1, l, r);
	return temp;
}
inline void point_modify(int rt, int pos, int val)
{
	if (t[rt].l == t[rt].r)
	{
		t[rt].sum += val;
		return;
	}
	if (pos <= t[rt << 1].r)point_modify(rt << 1, pos, val);
	else point_modify(rt << 1 | 1, pos, val);
	t[rt].sum = t[rt << 1].sum + t[rt << 1 | 1].sum;
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> a[i], suma[i] = suma[i - 1] + a[i];
	build(1, 1, n);
	cin >> Q;
	while (Q--)
	{
		bool f;
		cin >> f;
		if (f)
		{
			int l, r;
			cin >> l >> r;
			cout << interval_add(1, l, r) << "\n";
		}
		else
		{
			int p, v;
			cin >> p >> v;
			point_modify(1, p, v);
			a[p] += v;
			for (int i = 1; i <= n; i++)cout << a[i] << " ";
			cout << "\n";
		}
	}
}

二.区间修改,单点查询

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
int n, Q;
int a[maxn];
int suma[maxn];
typedef struct
{
	int l, r;
	int sum;
}T;
T t[maxn << 1];

inline void build(int rt, int l, int r)
{
	t[rt].l = l;
	t[rt].r = r;
	if (l == r)
	{
		t[rt].sum = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid + 1, r);
}
inline void interval_modify(int rt, int l, int r, int val)
{
	if (t[rt].l >= l && t[rt].r <= r)
	{
		t[rt].sum += val;
		return;
	}
	int mid = t[rt].l + t[rt].r >> 1;
	if (l <= mid)interval_modify(rt << 1, l, r, val);
	if (r > mid)interval_modify(rt << 1 | 1, l, r, val);
}
inline int point_ask(int rt, int pos)
{
	int ans = 0;
	ans += t[rt].sum;
	if (t[rt].l == t[rt].r)return ans;
	int mid = t[rt].l + t[rt].r >> 1;
	if (pos <= mid) ans += point_ask(rt << 1, pos);
	if (pos > mid)ans += point_ask(rt << 1 | 1, pos);
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n; cin >> Q;
	for (int i = 1; i <= n; i++)cin >> a[i], suma[i] = suma[i - 1] + a[i];
	build(1, 1, n);

	while (Q--)
	{
		bool f;
		cin >> f;
		if (f)
		{
			int l, r, v;
			cin >> l >> r >> v;
			interval_modify(1, l, r, v);
			for (int i = l; i <= r; i++)a[i] += v;
			for (int i = 1; i <= n; i++)cout << a[i] << " ";
			cout << "\n";
		}
		else
		{
			int pos;
			cin >> pos;
			cout << point_ask(1, pos) << "\n";
		}
	}
	return 0;
}

扫描线法

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
typedef struct line
{
	double x, y1, y2;
	int c;
	bool friend operator <(line p, line q)
	{
		return p.x < q.x;
	}
}A;
A a[maxn << 1];
typedef struct tree
{
	int l, r;
	int cnt;
	double len;
}T;
T t[maxn << 2];
int n;
double raw[maxn << 1];
int cnt;
double ans;
int val[maxn << 1][2];

inline void build(int rt, int l, int r)
{
	t[rt].l = l;
	t[rt].r = r;
	t[rt].cnt = 0;
	t[rt].len = 0;
	if (l == r)return;
	int mid = l + r >> 1;
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid + 1, r);
}
void push_up(int rt)
{
	if (t[rt].cnt > 0)t[rt].len = raw[t[rt].r + 1] - raw[t[rt].l];
	else if (t[rt].l == t[rt].r)t[rt].len = 0;
	else t[rt].len = t[rt << 1].len + t[rt << 1 | 1].len;
}
void interval_modify(int rt, int l, int r, int val)
{
	if (t[rt].l >= l && t[rt].r <= r)
	{
		t[rt].cnt += val;
		push_up(rt);
		return;
	}
	int mid = t[rt].l + t[rt].r >> 1;
	if (l <= mid)interval_modify(rt << 1, l, r, val);
	if (r > mid)interval_modify(rt << 1 | 1, l, r, val);
	push_up(rt);
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int casenum = 0;
	while (cin >> n && n)
	{
		cnt = 0;
		ans = 0;
		for (int i = 1; i <= n; i++)
		{
			double x1, y1, x2, y2;
			cin >> x1 >> y1 >> x2 >> y2;
			a[i * 2 - 1] = { x1,y1,y2,1 };
			a[i * 2] = { x2,y1,y2,-1 };
			raw[++cnt] = y1;
			raw[++cnt] = y2;
		}
		sort(a + 1, a + 1 + 2 * n);
		sort(raw + 1, raw + 1 + cnt);
		cnt = unique(raw + 1, raw + 1 + cnt) - (raw + 1);
		for (int i = 1; i <= n * 2; i++)
		{
			val[i][0] = lower_bound(raw + 1, raw + 1 + cnt, a[i].y1) - raw;
			val[i][1] = lower_bound(raw + 1, raw + 1 + cnt, a[i].y2) - raw;
		}
		build(1, 1, cnt);
		for (int i = 1; i <= 2 * n; i++)
		{
			interval_modify(1, val[i][0], val[i][1] - 1, a[i].c);
			ans += (a[i + 1].x - a[i].x) * t[1].len;
		}
		cout << "Test case #" << ++casenum << "\n";
		cout << "Total explored area: " << fixed << setprecision(2) << ans << "\n";
		cout << "\n";
	}
	return 0;
}

单点修改,区间查询最大子段和

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 100;
int n, Q;
int a[maxn];
int suma[maxn];
typedef struct node
{
	int l, r;
	int sum;
	int dat;
	int lmax, rmax;
	node()
	{
		l = r = sum = dat = lmax = rmax = 0;
	}
}T;
T t[maxn << 2];

inline void build(int rt, int l, int r)
{
	t[rt].l = l;
	t[rt].r = r;
	if (l == r)
	{
		t[rt].sum = a[l];
		t[rt].lmax = t[rt].rmax = t[rt].dat = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid + 1, r);
	t[rt].sum = t[rt << 1].sum + t[rt << 1 | 1].sum;
	t[rt].lmax = max(t[rt << 1].lmax, t[rt << 1].sum + t[rt << 1 | 1].lmax);
	t[rt].rmax = max(t[rt << 1 | 1].rmax, t[rt << 1].rmax + t[rt << 1 | 1].sum);
	t[rt].dat = max(t[rt << 1].dat, t[rt << 1 | 1].dat);
	t[rt].dat = max(t[rt].dat, t[rt << 1].rmax + t[rt << 1 | 1].lmax);
}

inline void point_modify(int rt, int pos, int val)
{
	if (t[rt].l == t[rt].r)
	{
		t[rt].sum = t[rt].dat = t[rt].lmax = t[rt].rmax = val;
		return;
	}
	int mid = t[rt].l + t[rt].r >> 1;

	if (pos <= mid)point_modify(rt << 1, pos, val);
	else point_modify(rt << 1 | 1, pos, val);
	t[rt].sum = t[rt << 1].sum + t[rt << 1 | 1].sum;
	t[rt].lmax = max(t[rt << 1].lmax, t[rt << 1].sum + t[rt << 1 | 1].lmax);
	t[rt].rmax = max(t[rt << 1 | 1].rmax, t[rt << 1].rmax + t[rt << 1 | 1].sum);
	t[rt].dat = max(t[rt << 1].dat, t[rt << 1 | 1].dat);
	t[rt].dat = max(t[rt].dat, t[rt << 1].rmax + t[rt << 1 | 1].lmax);
	return;
}

T interval_ask(int rt, int l, int r)                       
{	
	//此时的ask函数返回的是临时开的T,想一想为什么,如果是void类型ask,每次ask一个区间(l,r)dat,lmax,rmax都会随着l,r不同而修改,一定会影响后续ask
	if (t[rt].l >= l && t[rt].r <= r)return t[rt];
	int mid = t[rt].l + t[rt].r >> 1;

	if (l <= mid && r > mid)
	{
		T tt, tl, tr;
		tl = interval_ask(rt << 1, l, r);
		tr = interval_ask(rt << 1 | 1, l, r);
		tt.sum = tl.sum + tr.sum;
		tt.lmax = max(tl.lmax, tl.sum + tr.lmax);
		tt.rmax = max(tr.rmax, tl.rmax + tr.sum);
		tt.dat = max(tl.dat, tr.dat);
		tt.dat = max(tt.dat, tl.rmax + tr.lmax);
		return tt;
	}
	else if (l <= mid)
	{
		return interval_ask(rt << 1, l, r);
	}
	else if (r > mid)
	{
		return interval_ask(rt << 1 | 1, l, r);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> Q;
	for (int i = 1; i <= n; i++)cin >> a[i];
	build(1, 1, n);
	while (Q--)
	{
		int k, x, y;
		cin >> k >> x >> y;
		if (k & 1)
		{
			if (x > y)swap(x, y);
			T ans = interval_ask(1, x, y);
			cout << ans.dat << "\n";
		}
		else
		{
			point_modify(1, x, y);
		}
	}
	return 0;
}

图论补充:第K短路(A*)

//Made In Heaven
#pragma GCC optimize(3, "Ofast", "inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 1000;
int n, m;
int S, E, K, T;
int dis[maxn];
int h1[maxn], h2[maxn];
bool vis1[maxn];
int num1, num2;
typedef struct
{
    int nt, to, w;
}EDGE;
EDGE e1[maxn], e2[maxn];
void add1(int u, int v, int w)
{
    e1[++num1].w = w;
    e1[num1].to = v;
    e1[num1].nt = h1[u];
    h1[u] = num1;
}
void add2(int v, int u, int w)
{
    e2[++num2].w = w;
    e2[num2].to = v;
    e2[num2].nt = h2[u];
    h2[u] = num2;
}
typedef pair<int, int>P;
//反向建边dj  T->S
void dj()
{
    memset(dis, 0x3f, sizeof(dis));
    dis[E] = 0;
    priority_queue<P, vector<P>, greater<P> >q;
    q.push(make_pair(dis[E], E));
    while (!q.empty())
    {
        P p = q.top();
        q.pop();
        int u = p.second;
        int diss = p.first;
        if (vis1[u])continue;
        vis1[u] = 1;
        for (int i = h2[u]; i; i = e2[i].nt)
        {
            int v = e2[i].to;
            if (dis[v] > diss + e2[i].w)
            {
                dis[v] = diss + e2[i].w;
                q.push(make_pair(dis[v], v));
            }
        }
    }
}
typedef pair<int, P>PP;
int A_start()
{
    if (dis[S] >= 0x3f3f3f3f)return -1;
    priority_queue<PP, vector<PP>, greater<PP> >q;
    q.push(make_pair(dis[S], make_pair(0, S)));
    int cnt = 0;
    while (!q.empty())
    {
        PP p = q.top();
        q.pop();
        int u = p.second.second;
        int diss = p.second.first;
        if (u == E)cnt++;
        if (cnt == K)return diss;
        for (int i = h1[u]; i; i = e1[i].nt)
        {
            int v = e1[i].to;
            q.push(make_pair(diss + e1[i].w + dis[v], make_pair(diss + e1[i].w, v)));
        }
    }
    return -1;
}

void init() {
    num1 = num2 = 0;
    memset(vis1, 0, sizeof vis1);
    memset(h1, 0, sizeof h1);
    memset(h2, 0, sizeof h2);
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    while (cin >> n >> m) {
        init();
        cin >> S >> E >> K >> T;
        if (S == E)K++;
        while (m--)
        {
            int u, v, w;
            cin >> u >> v >> w;
            add1(u, v, w);
            add2(u, v, w);
        }
        dj();
        int ans = A_start();
        if (ans == -1 || ans > T)cout << "Whitesnake!\n";
        else cout << "yareyaredawa\n";
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值