区间前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 }

 

posted @ 2019-08-09 17:26  ZMWLxh  阅读(835)  评论(0编辑  收藏  举报