单点更新:最最基础的线段树,只更新叶子节点,然后把信息用 PushUP(int r)这个函数更新上来。
hdu1166 敌兵布阵
线段树功能:update:单点增减 query:区间求和
#include <bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int MAXN = 50550; int sum[MAXN << 2]; void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l, int r, int rt) { if (l == r) { scanf("%d",&sum[rt]); return; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int pos,int res,int l,int r,int rt) { if(l==r) { sum[rt]+=res; return; } int m=(l+r)>>1; if(pos<=m) { update(pos,res,lson); } else { update(pos,res,rson); } pushup(rt); } int query(int ql,int qr,int l,int r,int rt) { if(ql<=l && r<=qr) { return sum[rt]; } int res=0; int m=(l+r)>>1; if(ql<=m) { res+=query(ql,qr,lson); } if(qr>m) { res+=query(ql,qr,rson); } return res; } int main() { int t, n; scanf("%d",&t); int casee=1; char tmp[8]; int a,b; while (t--) { scanf("%d",&n); build(1, n, 1); printf("Case %d:\n",casee++); while(scanf("%s",tmp)) { if(tmp[0]=='E') { break; } scanf("%d%d",&a,&b); if(tmp[0]=='A') { update(a,b,1,n,1); } else if(tmp[0]=='S') { update(a,-b,1,n,1); } else { printf("%d\n",query(a,b,1,n,1)); } } } return 0; }
hdu1754 I Hate It
线段树功能:update:单点替换 query:区间最值
#include <bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int MAXN = 200550; int sum[MAXN << 2]; void pushup(int rt) { sum[rt] = max(sum[rt << 1], sum[rt << 1 | 1]); } void build(int l, int r, int rt) { if (l == r) { scanf("%d", &sum[rt]); return; } int m = (l + r) >> 1; build(lson); build(rson); pushup(rt); } void update(int pos, int res, int l, int r, int rt) { if (l == r) { sum[rt] = res; return; } int m = (l + r) >> 1; if (pos <= m) { update(pos, res, lson); } else { update(pos, res, rson); } pushup(rt); } int query(int ql, int qr, int l, int r, int rt) { if (ql <= l && r <= qr) { return sum[rt]; } int res = 0; int m = (l + r) >> 1; if (ql <= m) { res = max(res, query(ql, qr, lson)); } if (qr > m) { res = max(res, query(ql, qr, rson)); } return res; } int main() { int n, m; int a, b; while (~scanf("%d%d", &n, &m)) { build(1, n, 1); char tmp; while (m--) { cin >> tmp; scanf("%d%d", &a, &b); if (tmp == 'U') { update(a, b, 1, n, 1); } else { printf("%d\n", query(a, b, 1, n, 1)); } } } return 0; }
hdu1394 Minimum Inversion Number
题意:求 Inversion 后的最小逆序数
思路:用 O(nlogn)复杂度求出最初逆序数后,就可以用 O(1)的复杂度分别递推出其他
解
线段树功能:update:单点增减 query:区间求和
import java.util.*; import java.math.*; public class Main { static int MAXN = 5050; static int[] sum = new int[MAXN << 2]; public static void pushup(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } public static void bulid(int l, int r, int rt) { sum[rt] = 0; if (r == l) { return; } int m = (l + r) >> 1; bulid(l, m, rt << 1); bulid(m + 1, r, rt << 1 | 1); pushup(rt); } public static void update(int add, int l, int r, int rt) { if (l == r) { sum[rt]++; return; } int m = (l + r) >> 1; if (add <= m) { update(add, l, m, rt << 1); } else { update(add, m + 1, r, rt << 1 | 1); } pushup(rt); } public static int query(int L, int R, int l, int r, int rt) { if (L <= l && r <= R) { return sum[rt]; } int res = 0; int m = (l + r) >> 1; if (L <= m) { res += query(L, R, l, m, rt << 1); } if (R > m) { res += query(L, R, m + 1, r, rt << 1 | 1); } return res; } public static void main(String[] args) { Scanner cin = new Scanner(System.in); int n; int[] a = new int[5050]; while (cin.hasNext()) { n = cin.nextInt(); bulid(0, n - 1, 1); int sum = 0; for (int i = 0; i < n; ++i) { a[i] = cin.nextInt(); sum += query(a[i], n - 1, 0, n - 1, 1); update(a[i], 0, n - 1, 1); } int ans = sum; for (int i = 0; i < n; ++i) { sum += n - a[i] - a[i] - 1; ans = Math.min(ans, sum); } System.out.println(ans); } cin.close(); } }
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/652 (转载时请注明本文出处及文章链接)
发表评论
快来吐槽一下吧!