区间前k小的和(权值线段树+离散化)--2019牛客多校第7场C--砍树
题目链接:https://ac.nowcoder.com/acm/contest/887/C?&headNav=acm
题意:
给你 n 种树,有 高度,花费和数量 ,现在问你最少需要花多少钱使得最高的树的数量占总数的一半以上。
思路:
其实就是先把高度离散化一下(不离散化也没事),再按树的高度从低到高排一下序,枚举最高的树。
比如当前枚举的是 H,那花费就是(>H)的树的所有花费+(<H)的最多剩下num-1棵树,用权值线段树记录花费和花费的个数,每次查询前k小个就可以了。
1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include <cstdlib>//malloc exit strcat itoa system("cls") 4 #include <iostream>//pair 5 #include <fstream> 6 #include <bitset> 7 //#include <map> 8 //#include<unordered_map> https://ac.nowcoder.com/acm/contest/887/C?&headNav=acm 9 #include <vector> 10 #include <stack> 11 #include <set> 12 #include <string.h>//strstr substr 13 #include <string> 14 #include <time.h>//srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9; 15 #include <cmath> 16 #include <deque> 17 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less 18 #include <vector>//emplace_back 19 //#include <math.h> 20 //#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor 21 #include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare) 22 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation 23 #define fo(a,b,c) for(register int a=b;a<=c;++a) 24 #define fr(a,b,c) for(register int a=b;a>=c;--a) 25 #define mem(a,b) memset(a,b,sizeof(a)) 26 #define pr printf 27 #define sc scanf 28 #define ls rt<<1 29 #define rs rt<<1|1 30 void swapp(int &a,int &b); 31 double fabss(double a); 32 int maxx(int a,int b); 33 int minn(int a,int b); 34 int Del_bit_1(int n); 35 int lowbit(int n); 36 int abss(int a); 37 const long long INF=(1LL<<60); 38 const double E=2.718281828; 39 const double PI=acos(-1.0); 40 const int inf=(1<<29); 41 const double ESP=1e-9; 42 const int mod=(int)1e9+7; 43 const int N=(int)1e5+10; 44 45 int n; 46 struct node_ 47 { 48 int h,num,cost; 49 friend bool operator<(node_ a,node_ b) 50 { 51 return a.h>b.h; 52 } 53 }arr[N]; 54 int b[N]; 55 int LS(int n) 56 { 57 int m=0; 58 for(int i=1; i<=n; ++i) 59 b[++m]=arr[i].h; 60 sort(b+1,b+1+m); 61 m=unique(b+1,b+1+m)-b-1; 62 for(int i=1; i<=n; ++i) 63 arr[i].h=lower_bound(b+1,b+1+m,arr[i].h)-b; 64 return m; 65 } 66 //================================================离散化; 67 struct node 68 { 69 long long cnt; 70 long long sum; 71 }tr[N<<2]; 72 void Build(int l,int r,int rt) 73 { 74 tr[rt].sum=tr[rt].cnt=0; 75 if(l==r)return; 76 int mid=(l+r)>>1; 77 Build(l,mid,rt<<1); 78 Build(mid+1,r,rt<<1|1); 79 } 80 void update_dot(int cost,int cnt,int l,int r,int rt) 81 { 82 tr[rt].sum+=cost*cnt; 83 tr[rt].cnt+=cnt; 84 if(l==r)return; 85 86 int mid=(l+r)>>1; 87 if(cost<=mid) 88 update_dot(cost,cnt,l,mid,rt<<1); 89 else 90 update_dot(cost,cnt,mid+1,r,rt<<1|1); 91 } 92 long long Query(long long sum,int l,int r,int rt) 93 { 94 if(sum==0)return 0; 95 if(l==r) 96 { 97 return sum*l; 98 } 99 int mid=(l+r)>>1; 100 long long ans=0; 101 102 if(sum<=tr[ls].cnt) 103 ans+=Query(sum,l,mid,ls); 104 else 105 ans+=Query(sum-tr[ls].cnt,mid+1,r,rs)+tr[ls].sum; 106 return ans; 107 } 108 void check(int pos,int l,int r,int rt) 109 { 110 if(l==r) 111 { 112 pr("%lld %lld\n",tr[rt].cnt,tr[rt].sum); 113 return ; 114 } 115 int mid=(l+r)>>1; 116 117 if(pos<=mid) 118 check(pos,l,mid,rt<<1); 119 else 120 check(pos,mid+1,r,rt<<1|1); 121 } 122 void C(int tot) 123 { 124 fo(i,1,n) 125 check(i,1,tot,1); 126 pr("----------------------------------\n"); 127 } 128 long long dp[N]; 129 vector<vector<int> >v(N); 130 131 int main() 132 { 133 while(~sc("%d",&n)) 134 { 135 fo(i,1,n)sc("%d%d%d",&arr[i].h,&arr[i].cost,&arr[i].num); 136 arr[n+1].num=arr[n+1].cost=arr[n+1].h=0; 137 LS(n); 138 sort(arr+1,arr+1+n); 139 fo(i,1,n) 140 dp[i]=dp[i-1]+arr[i].cost*arr[i].num,v[i].clear(); 141 long long ans=INF; 142 int vcnt=0; 143 long long cnt=0; 144 long long CNT=0; 145 int ncnt=0; 146 for(int i=n;i>=1;--i) 147 { 148 if(arr[i].h!=arr[i+1].h) 149 v[++vcnt].push_back(i); 150 else 151 v[vcnt].push_back(i); 152 } 153 Build(1,200,1); 154 int sz=v[1].size();//vector用来存相同高度的树团体 155 fo(i,0,sz-1) 156 update_dot(arr[v[1][i]].cost,arr[v[1][i]].num,1,200,1),CNT+=arr[v[1][i]].num; 157 ans=min(ans,dp[n-sz]); 158 ncnt=sz; 159 fo(i,2,vcnt) 160 { 161 int sz_=v[i].size(); 162 fo(j,0,sz_-1) 163 cnt+=arr[v[i][j]].num; 164 ncnt+=sz_; 165 long long k=max(0LL,CNT-(cnt-1)); 166 ans=min(ans,Query(k,1,200,1)+dp[n-ncnt]); 167 fo(j,0,sz_-1) 168 update_dot(arr[v[i][j]].cost,arr[v[i][j]].num,1,200,1); 169 CNT+=cnt; 170 cnt=0; 171 } 172 pr("%lld\n",ans); 173 } 174 return 0; 175 } 176 177 /**************************************************************************************/ 178 179 int maxx(int a,int b) 180 { 181 return a>b?a:b; 182 } 183 184 void swapp(int &a,int &b) 185 { 186 a^=b^=a^=b; 187 } 188 189 int lowbit(int n) 190 { 191 return n&(-n); 192 } 193 194 int Del_bit_1(int n) 195 { 196 return n&(n-1); 197 } 198 199 int abss(int a) 200 { 201 return a>0?a:-a; 202 } 203 204 double fabss(double a) 205 { 206 return a>0?a:-a; 207 } 208 209 int minn(int a,int b) 210 { 211 return a<b?a:b; 212 }