hdu 5700 區間交(線段樹)
阿新 • • 發佈:2018-11-22
好久沒做這種題都不太會了。想法是先排序然後就大概有個方向了。
#include <stdio.h> #include <string.h> #include <ctime> #include <stack> #include <string> #include <algorithm> #include <iostream> #include <cmath> #include <map> #include <queue> #include <vector> using namespace std; #define LL long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lowbit(x) (x&-x) const int maxn = 1e5+5; const int INF = 0x3f3f3f3f; LL sum[maxn]; int tree[maxn<<2]; struct Node { int l,r; bool operator<(const Node& cmp) const { if(r==cmp.r) return l<cmp.l; return r>cmp.r; } }a[maxn]; void update(int o,int l,int r,int rt) { if(l==r) { tree[rt] += 1; return ; } int m = (l+r)>>1; if(o<=m) update(o,lson); else update(o,rson); tree[rt] = tree[rt<<1] + tree[rt<<1|1]; } int query(int k,int l,int r,int rt) { if(l==r) return l; int m = (l+r)>>1; if(k<=tree[rt<<1]) return query(k,lson); else return query(k-tree[rt<<1],rson); } int main() { int n,m,k; while(scanf("%d%d%d",&n,&k,&m)!=EOF) { memset(tree,0,sizeof(tree)); for(int i=1; i<=n; i++) { int u; scanf("%d",&u); sum[i] = sum[i-1]+u; } for(int i=0; i<m; i++) scanf("%d%d",&a[i].l,&a[i].r); sort(a,a+m); for(int i=0; i<k-1; i++) update(a[i].l,1,n,1); LL ans = 0; for(int i=k-1; i<m; i++) { update(a[i].l,1,n,1); int l = query(k,1,n,1); if(l<=a[i].r) ans = max(ans,sum[a[i].r]-sum[l-1]); } cout<<ans<<endl; } return 0; }
區間交
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1091 Accepted Submission(s): 431
Problem Description 小A有一個含有 n個非負整數的數列與 m個區間。每個區間可以表示為 li,ri。
它想選擇其中 k個區間, 使得這些區間的交的那些位置所對應的數的和最大。
例如樣例中,選擇
Input 多組測試資料
第一行三個數 n,k,m(1≤n≤100000,1≤k≤m≤100000)。
接下來一行 n個數 ai,表示lyk的數列 (0≤ai≤109)。
接下來 m行,每行兩個數 li,ri,表示每個區間 (1≤li≤ri≤n)。
Output 一行表示答案
Sample Input
Sample Output 10