【Foreign】数据结构C [线段树]

本文介绍了一种利用权值线段树解决特定数据结构问题的方法,通过离线处理将删除操作转化为合并操作,实现了单点修改、查询第k大及信息合并的功能。

数据结构C

Time Limit: 20 Sec  Memory Limit: 512 MB

Description

  

Input

  

Output

  

Sample Input

  

Sample Output

  

HINT

  

Solution

  首先,D操作为删除操作显然不可做,又发现这道题可以离线处理,那么我们考虑倒着来,维护加入操作。

  那么这时候,D操作就变为了合并操作,那么这时候我们只需要维护一个:可以支持单点修改查询第 k 大信息可合并的数据结构即可。

  显然构建若干棵权值线段树即可!对于每个联通块维护一棵线段树,用并查集判断两点是否在一个块内。

  这时候,D操作显然判断一下两点是否在一个联通块内,不在则合并两棵线段树;Q操作就是查询第 k 大,在树上二分即可;C操作就是原来值个数-1新加入值个数+1

  就简单地解决了这题啦!(本质上就是BZOJ1926弱化 + BZOJ1015 QWQ

Code

  1 #include<iostream>  
  2 #include<algorithm>  
  3 #include<cstdio>  
  4 #include<cstring>  
  5 #include<cstdlib>  
  6 #include<cmath>  
  7 using namespace std;
  8    
  9 const int ONE = 1000005;
 10 const int INF = 2e6;
 11 const int Base = 1e6;
 12 
 13 int n, m;
 14 int opt, x, val;
 15 int Val[100005];
 16 char s[5];
 17 
 18 int Ans[300005], ans_num = 0;
 19 
 20 int fat[100005];
 21 
 22 int Num = 0, del[100005];
 23 struct power {int opt, x, val;} oper[ONE];
 24 struct point {int x, y;} a[100005];
 25 int total = 0;
 26 struct seg
 27 {
 28         int root;
 29         int left, right;
 30         int val;
 31 }Node[ONE * 4];
 32 
 33 int get()
 34 {
 35         int res=1,Q=1;    char c;
 36         while( (c=getchar())<48 || c>57)
 37         if(c=='-')Q=-1;
 38         if(Q) res=c-48; 
 39         while((c=getchar())>=48 && c<=57) 
 40         res=res*10+c-48; 
 41         return res*Q; 
 42 }
 43 
 44 int Find(int x)
 45 {
 46         if(fat[x] == x) return x;
 47         return fat[x] = Find(fat[x]);
 48 }
 49 
 50 void Un(int x, int y)
 51 {
 52         int f1 = Find(x), f2 = Find(y);
 53         if(f1 != f2) fat[f1] = f2;
 54 }
 55 
 56 void Update(int &i, int l, int r, int Val, int opt) //pos = Val , + opt
 57 {
 58         if(!i) i = ++total;
 59         
 60         Node[i].val = Node[i].val + opt;
 61         
 62         if(l == r) return;
 63         int mid = l + r >> 1;
 64         
 65         if(Val <= mid) Update(Node[i].left, l, mid, Val, opt);
 66         else Update(Node[i].right, mid + 1, r, Val, opt);
 67         
 68 }
 69 
 70 int Merge(int y, int x) //y merge to x
 71 {
 72         if(x == 0 || y == 0) return x + y;
 73         
 74         Node[x].val += Node[y].val;
 75         Node[x].left =  Merge(Node[x].left, Node[y].left);
 76         Node[x].right = Merge(Node[x].right, Node[y].right);
 77     
 78         return x;
 79 }
 80 
 81 int Query(int i, int l, int r, int k) //k da
 82 {
 83         if(l == r) return l;
 84         int mid = l + r >> 1, Val = Node[ Node[i].right ].val;
 85         
 86         if(k > Val)
 87             return Query(Node[i].left, l, mid, k - Val);
 88         else
 89             return Query(Node[i].right, mid + 1, r, k);
 90 }
 91 
 92 void Deal_first()
 93 {
 94         for(int i = 1; i <= n; i++)
 95             fat[i] = i, Node[i].root = ++total;
 96         for(int i = 1; i <= m; i++)
 97             if(del[i] != 1) Un(a[i].x, a[i].y);
 98         for(int i = 1; i <= n; i++)
 99             Update(Node[Find(i)].root, 0, INF, Val[i], 1);
100 }
101 
102 void Deal_add(int x, int y)
103 {
104         x = Find(x), y = Find(y);
105         if(x == y) return;
106         Merge(Node[x].root, Node[y].root);
107         fat[x] = y;
108 }
109 
110 void Deal_query(int root, int k)
111 {
112         root = Find(root);
113         if(Node[root].val < k) {Ans[++ans_num] = 0 + Base; return;}
114         Ans[++ans_num] = Query(Node[root].root, 0, INF, k);
115 }
116 
117 void Deal_change(int x, int y) //x is point, y is need val
118 {
119         int root = Find(x);
120         Update(Node[root].root, 0, INF, Val[x], -1);
121         Update(Node[root].root, 0, INF, y, 1);
122         Val[x] = y;
123 }
124 
125 int main()
126 {
127         n = get();    m = get();
128         
129         for(int i = 1; i <= n; i++) Val[i] = get() + Base;
130         for(int i = 1; i <= m; i++)
131             a[i].x = get(), a[i].y = get();
132         for(;;)
133         {
134             scanf("%s", s);
135             if(s[0] == 'E') break;
136             if(s[0] == 'D')
137                 x = get(), del[x] = 1, oper[++Num] = (power){1, x, 0};
138             if(s[0] == 'Q')
139                 x = get(), val = get(), oper[++Num] = (power){2, x, val};
140             if(s[0] == 'C')
141                 x = get(), val = get(), oper[++Num] = (power){3, x, Val[x]}, Val[x] = val + Base;
142         }
143         
144         Deal_first();
145         for(int i = Num; i >= 1; i--)
146         {
147             if(oper[i].opt == 1) Deal_add(a[ oper[i].x ].x, a[ oper[i].x ].y);
148             if(oper[i].opt == 2) Deal_query(oper[i].x, oper[i].val);
149             if(oper[i].opt == 3) Deal_change(oper[i].x, oper[i].val);
150         }
151         
152         for(int i = ans_num; i >= 1; i--)
153             printf("%d\n", Ans[i] - Base);
154 }
View Code

 

  • [提交][状态][讨论]

转载于:https://www.cnblogs.com/BearChild/p/7663495.html

#include <bits/stdc++.h> using namespace std; typedef long long ll; #define INF 0x7ffffff #define rep(i,s,t) for(register ll i = s;i <= t;++i) #define per(i,t,s) for(register ll i = t;i >= s;--i) const ll N = 1e5 + 5; const ll M = 5e5 + 5; ll n; ll m; ll q; ll ans = -INF; ll a[N] = {}; ll b[N] = {}; class segment_tree { private: struct node { ll l; ll r; ll maxn; ll minn; }; node t[M]; inline ll lson(ll p) { return p << 1; } inline ll rson(ll p) { return p << 1 | 1; } inline void push_up(ll p) { t[p].maxn = max(t[lson(p)].maxn,t[rson(p)].maxn); t[p].minn = min(t[lson(p)].minn,t[rson(p)].minn); } public: inline void build(ll p,ll l,ll r) { t[p].l = l; t[p].r = r; if(l == r) { t[p].maxn = 0; t[p].minn = 0; return; } ll mid = l + r >> 1; build(lson(p),l,mid); build(rson(p),mid + 1,r); push_up(p); } inline void update(ll p,ll x,ll k) { if(t[p].l == t[p].r) { t[p].maxn = k; t[p].minn = k; return; } ll mid = t[p].l + t[p].r >> 1; if(x <= mid) update(lson(p),x,k); else update(rson(p),x,k); push_up(p); } inline ll query_max(ll p,ll l,ll r) { if(l <= t[p].l && t[p].r <= r) return t[p].maxn; ll ans = -INF; ll mid = t[p].l + t[p].r >> 1; if(l <= mid) ans = max(ans,query_max(lson(p),l,r)); if(r > mid) ans = max(ans,query_max(rson(p),l,r)); return ans; } inline ll query_min(ll p,ll l,ll r) { if(l <= t[p].l && t[p].r <= r) return t[p].minn; ll ans = INF; ll mid = t[p].l + t[p].r >> 1; if(l <= mid) ans = min(ans,query_min(lson(p),l,r)); if(r > mid) ans = min(ans,query_min(rson(p),l,r)); return ans; } }; class dual_segment_tree { private: struct node { ll l; ll r; ll maxn = -INF; ll minn = INF; }; node t[M]; inline ll lson(ll p) { return p << 1; } inline ll rson(ll p) { return p << 1 | 1; } inline void push_up(ll p) { t[p].maxn = max(t[lson(p)].maxn,t[rson(p)].maxn); t[p].minn = min(t[lson(p)].minn,t[rson(p)].minn); } public: inline void build(ll p,ll l,ll r) { t[p].l = l; t[p].r = r; if(l == r) return; ll mid = l + r >> 1; build(lson(p),l,mid); build(rson(p),mid + 1,r); } inline void update(ll p,ll x,ll k,bool opt) { if(t[p].l == t[p].r) { if(opt) { t[p].maxn = -INF; t[p].minn = INF; } else { t[p].maxn = k; t[p].minn = k; } return; } ll mid = t[p].l + t[p].r >> 1; if(x <= mid) update(lson(p),x,k,opt); else update(rson(p),x,k,opt); push_up(p); } inline ll query_max(ll p,ll l,ll r) { if(l <= t[p].l && t[p].r <= r) return t[p].maxn; ll ans = -INF; ll mid = t[p].l + t[p].r >> 1; if(l <= mid) ans = max(ans,query_max(lson(p),l,r)); if(r > mid) ans = max(ans,query_max(rson(p),l,r)); return ans; } inline ll query_min(ll p,ll l,ll r) { if(l <= t[p].l && t[p].r <= r) return t[p].minn; ll ans = INF; ll mid = t[p].l + t[p].r >> 1; if(l <= mid) ans = min(ans,query_min(lson(p),l,r)); if(r > mid) ans = min(ans,query_min(rson(p),l,r)); return ans; } }; segment_tree t; dual_segment_tree pos; dual_segment_tree neg; inline ll read() { ll x = 0; ll y = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') y = -y; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + (c ^ '0'); c = getchar(); } return x * y; } inline void write(ll x) { if(x < 0) { putchar('-'); write(-x); return; } if(x > 9) write(x / 10); putchar(x % 10 + '0'); } int main() { n = read(); m = read(); q = read(); pos.build(1,1,n); neg.build(1,1,n); rep(i,1,n) { a[i] = read(); if(a[i] >= 0) { pos.update(1,i,a[i],false); neg.update(1,i,a[i],true); } else { pos.update(1,i,a[i],true); neg.update(1,i,a[i],false); } } rep(i,1,m) { b[i] = read(); t.update(1,i,b[i]); } rep(o,1,q) { ans = -INF; ll l1 = 0; ll r1 = 0; ll l2 = 0; ll r2 = 0; l1 = read(); r1 = read(); l2 = read(); r2 = read(); ll max_t = t.query_max(1,l2,r2); ll min_t = t.query_min(1,l2,r2); ll max_pos = pos.query_max(1,l1,r1); ll min_pos = pos.query_min(1,l1,r1); ll max_neg = neg.query_max(1,l1,r1); ll min_neg = neg.query_min(1,l1,r1); if(max_pos != -INF) ans = max(ans,max_pos * min_t); if(min_pos != INF) ans = max(ans,min_pos * min_t); if(max_neg != -INF) ans = max(ans,max_neg * max_t); if(min_neg != INF) ans = max(ans,min_neg * max_t); write(ans); putchar('\n'); } return 0; } #include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, s, t) for (ll i = (s); i <= (t); ++i) #define per(i, t, s) for (ll i = (t); i >= (s); --i) #define debug if (0) const ll INF = 1e18 + 1; class DualSegmentTree { private: struct Node { ll l, r; ll mx, mi; }; vector<Node> t; const bool type; // 0-非负 1-负 inline ll lson(ll p) { return p << 1; } inline ll rson(ll p) { return p << 1 | 1; } void push_up(ll p) { t[p].mx = max(t[lson(p)].mx, t[rson(p)].mx); t[p].mi = min(t[lson(p)].mi, t[rson(p)].mi); } public: DualSegmentTree(ll n, bool _type) : type(_type) { t.resize(n << 2); build(1, 1, n); } void build(ll p, ll l, ll r) { t[p].l = l, t[p].r = r; t[p].mx = -INF; t[p].mi = INF; if (l == r) return; ll mid = (l + r) >> 1; build(lson(p), l, mid); build(rson(p), mid + 1, r); } void insert(ll p, ll pos, ll val, bool is_foreign) { if (t[p].l == t[p].r) { if (is_foreign) { t[p].mx = -INF; t[p].mi = INF; } else { t[p].mx = t[p].mi = val; } return; } ll mid = (t[p].l + t[p].r) >> 1; if (pos <= mid) insert(lson(p), pos, val, is_foreign); else insert(rson(p), pos, val, is_foreign); push_up(p); } ll query_max(ll p, ll L, ll R) { if (t[p].l >= L && t[p].r <= R) return t[p].mx; ll mid = (t[p].l + t[p].r) >> 1; ll res = -INF; if (L <= mid) res = max(res, query_max(lson(p), L, R)); if (R > mid) res = max(res, query_max(rson(p), L, R)); return res; } ll query_min(ll p, ll L, ll R) { if (t[p].l >= L && t[p].r <= R) return t[p].mi; ll mid = (t[p].l + t[p].r) >> 1; ll res = INF; if (L <= mid) res = min(res, query_min(lson(p), L, R)); if (R > mid) res = min(res, query_min(rson(p), L, R)); return res; } }; class SimpleSegmentTree { private: struct Node { ll l, r; ll mx, mi; }; vector<Node> t; inline ll lson(ll p) { return p << 1; } inline ll rson(ll p) { return p << 1 | 1; } void push_up(ll p) { t[p].mx = max(t[lson(p)].mx, t[rson(p)].mx); t[p].mi = min(t[lson(p)].mi, t[rson(p)].mi); } public: SimpleSegmentTree(ll n) { t.resize(n << 2); build(1, 1, n); } void build(ll p, ll l, ll r) { t[p].l = l, t[p].r = r; if (l == r) { t[p].mx = t[p].mi = 0; // 初始值需外部设置 return; } ll mid = (l + r) >> 1; build(lson(p), l, mid); build(rson(p), mid + 1, r); push_up(p); } void insert(ll p, ll pos, ll val) { if (t[p].l == t[p].r) { t[p].mx = t[p].mi = val; return; } ll mid = (t[p].l + t[p].r) >> 1; if (pos <= mid) insert(lson(p), pos, val); else insert(rson(p), pos, val); push_up(p); } ll query_max(ll p, ll L, ll R) { if (t[p].l >= L && t[p].r <= R) return t[p].mx; ll mid = (t[p].l + t[p].r) >> 1; ll res = -INF; if (L <= mid) res = max(res, query_max(lson(p), L, R)); if (R > mid) res = max(res, query_max(rson(p), L, R)); return res; } ll query_min(ll p, ll L, ll R) { if (t[p].l >= L && t[p].r <= R) return t[p].mi; ll mid = (t[p].l + t[p].r) >> 1; ll res = INF; if (L <= mid) res = min(res, query_min(lson(p), L, R)); if (R > mid) res = min(res, query_min(rson(p), L, R)); return res; } }; inline ll read() { ll x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } ll a[100005], b[100005]; int main() { ll n = read(), m = read(), q = read(); DualSegmentTree pos_tr(n, 0); DualSegmentTree neg_tr(n, 1); rep(i, 1, n) { a[i] = read(); if (a[i] >= 0) { pos_tr.insert(1, i, a[i], false); neg_tr.insert(1, i, a[i], true); } else { neg_tr.insert(1, i, a[i], false); pos_tr.insert(1, i, a[i], true); } } SimpleSegmentTree b_tr(m); rep(i, 1, m) { b[i] = read(); b_tr.insert(1, i, b[i]); } while (q--) { ll l1 = read(), r1 = read(), l2 = read(), r2 = read(); ll maxz = pos_tr.query_max(1, l1, r1); ll minz = pos_tr.query_min(1, l1, r1); ll maxf = neg_tr.query_max(1, l1, r1); ll minf = neg_tr.query_min(1, l1, r1); ll maxb = b_tr.query_max(1, l2, r2); ll minb = b_tr.query_min(1, l2, r2); ll ans = -INF; if (maxz != -INF) ans = max(ans, maxz * minb); if (minz != INF) ans = max(ans, minz * minb); if (maxf != -INF) ans = max(ans, maxf * maxb); if (minf != INF) ans = max(ans, minf * maxb); printf("%lld\n", ans); } return 0; } 请针对洛谷P8818策略游戏,指出上述两段代码的区别,并精确保留第一段代码风格修正第一段代码
08-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值