Codeforces 458C Elections 贿赂选票抢主席! 线段树

题目链接:点击打开链接

题意:

给定n张选票,每张选票有2个参数,第一个参数表示这张选票选的人

第二个参数表示如果让这张选票改为选0号 的花费

问:使得0号的选票是最高的(不能有和0号相同)的最小花费

枚举0号的最终选票

那么已知0号最终选票,则有些人选票比0号大的,那些票都要买下来。

如果买完了还是达不到 最终选票,就从所有剩下的选票里找前k小的。

用线段树求前k小的数的和,然后_(:зゝ∠)_就可以了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
#define N 100005
#define inf 100000000
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Sum(x) tree[x].sum
#define Siz(x) tree[x].siz
#define Lson(x) tree[x].l
#define Rson(x) tree[x].r
inline int Mid(int x, int y){return (x+y)>>1;}
struct node{
    int l, r, siz, sum;
}tree[10004*4];
void push_up(int id){
    Sum(id) = Sum(L(id)) + Sum(R(id));
    Siz(id) = Siz(L(id)) + Siz(R(id));
}
void build(int l, int r, int id){
    Lson(id) = l, Rson(id) = r;
    Sum(id) = Siz(id) = 0;
    if(l==r) return ;
    int mid = Mid(l,r);
    build(l, mid, L(id));
    build(mid+1, r, R(id));
}
void updata(int pos, int val, int id){
    if(Lson(id) == Rson(id))
    {
        Siz(id) += val;
        Sum(id) += pos*val;
        return ;
    }
    int mid = Mid(Lson(id), Rson(id));
    if(pos <= mid)
        updata(pos, val, L(id));
    else
        updata(pos, val, R(id));
    push_up(id);
}
int query(int k, int id){
	if(k<=0)return 0;
	if(Siz(id) <= k)
    {
        return Sum(id);
    }
	if(Lson(id) == Rson(id)){
		return min(Siz(id), k) * Lson(id);
	}
    int mid = Mid(Lson(id), Rson(id));
    if(Siz(L(id)) <= k)
    {
        return Sum(L(id)) + query(k - Siz(L(id)), R(id));
    }
    else query(k, L(id));
}
vector<int> a[N], G[N];
int n, cost, now;
int work(int x){
    for(int i = 0; i < G[x].size(); i++)
    {
        cost += G[x][i];
        updata(G[x][i], -1, 1);
        now ++;
    }
    int hehe = x - now;
    if(hehe<=0)return cost;
    return cost+query(hehe, 1);
}
void input(){
    build(0, 10004, 1);
    for(int i = 0; i < N; i++)a[i].clear(), G[i].clear();
    for(int i = 1; i <= n; i++)
    {
		int u, v;
        scanf("%d %d",&u,&v);
        a[u].push_back(v);
        updata(v, 1, 1);
    }
    for(int i = 1; i < N; i++)sort(a[i].begin(), a[i].end());
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < a[i].size(); j++)
        {
            G[a[i].size() - j].push_back(a[i][j]);
        }
    }
}
int main(){
    int i, j, u, v;
    while(~scanf("%d",&n))
    {
        input();
        int ans = 1e9+10;
        cost = 0;
        now = 0;
        for(i = n; i >= 0; i--)
        {
            int tmp = work(i);
            if(tmp == -1)break;
            ans = min(ans, tmp);
        }
        cout<<ans<<endl;
    }
    return 0;
}

Codeforces 458C Elections 贿赂选票抢主席! 线段树

时间: 2024-10-28 21:24:27

Codeforces 458C Elections 贿赂选票抢主席! 线段树的相关文章

CodeForces 52C Circular RMQ(区间循环线段树,区间更新,区间求和)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://codeforces.com/problemset/problem/52/C You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segm

codeforces 446C DZY Loves Fibonacci Numbers 数论+线段树成段更新

DZY Loves Fibonacci Numbers Time Limit:4000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-14) Description In mathematical terms, the sequence Fn of Fibonacci numbers is defi

Codeforces Beta Round #12 D. Ball (线段树)

题目大意: n个女性中,如果有一个女性的三维比这个女性的三维都大,这个女性就要自杀.问要自杀多少个. 思路分析: 先按照第一维排序. 然后离散化第二维,用第二维的下标建树,树上的值是第三维,更新的时候取最大值. 注意是按照第一维度从大到小进入线段树. 而且还要严格递增. 所以处理第一维度比较大小的时候要分开处理,要把相同的先判断,再更新入树. 那么如何判断这个女性是否自杀. 首先,你知道第一维度是从大到小的,所以先进树了的节点的第一维度一定更大. 再次,我们考虑第二维度,我们去树上第二维度下标大

Codeforces 458C - Elections

458C - Elections 思路: 三分凹形函数极小值域 代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e5+5; const int INF=0x7f7f7f7f; vector<int>g[N],vc; int n; int cost(

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Codeforces 484E Sign on Fence(可持久化线段树+二分)

题目链接:Codeforces 484E Sign on Fence 题目大意:给定给一个序列,每个位置有一个值,表示高度,现在有若干查询,每次查询l,r,w,表示在区间l,r中, 连续最长长度大于w的最大高度为多少. 解题思路:可持久化线段树维护区间合并,前端时间碰到一题可持久化字典树,就去查了一下相关论文,大概知道了是 什么东西. 将高度按照从大到小的顺序排序,然后每次插入一个位置,线段树维护最长连续区间,因为插入是按照从大到小的顺 序,所以每次的线段树中的连续最大长度都是满足高度大于等于当

Codeforces Round #401 (Div. 2) E 贪心,线段树

Codeforces Round #401 (Div. 2) A 循环节 B 暴力排一下 C 标记出来,但10^5,特耿直地码了个O(n^2)的上去,最气的是在最后3分钟的时候被叉== D 从后往前贪心暴糙一下就好.比赛时一眼瞄出来了不敢写,搞不懂这样竟然不会超时.. E. Hanoi Factory 题意:n个环体,内径a[i],外径b[i],高h[i].当 a[i+1]<b[i]<=b[i+1] 时,第 i 个环体可以堆在第 i+1个环体上.求可以堆出的最高高度. tags:佩服那些大佬,

codeforces 340D D. Bubble Sort Graph(dp+线段树)

题目链接: codeforces 340D 题目大意: 给出一个程序,就是冒泡排序,每次如果发现相邻两个数前一个大于后一个,交换位置后建边,问最后得到的这个图中的最大独立集,这个最大独立集定义为所有的点都不相邻的最大点的集合的规模. 题目分析: 首先我们可以知道对于a[i],它只会且一定会与后面的比它小的建边,所以我们只需要固定第一个点,然后找最长上升子序列即可.(这样能够保证没有相邻的点) 定义状态dp[i]为以i项结尾的最长上升子序列的长度. 转移方程如下: dp[i]=max{dp[j]+

Codeforces 242E. XOR on Segment (二维线段树 lazy操作 xor)

题目链接: http://codeforces.com/problemset/problem/242/E 题意: 给出一个序列,有两种操作,一种是计算l到r的和,另一种是让l到r的数全部和x做异或运算. 思路: from: http://blog.csdn.net/u013912596/article/details/39006317 很显然直接暴力是不可能的,又是两种操作,又想到了线段树..但是这并不简单,异或操作该怎么处理? 异或是一种位运算,如果x的第j位是1,那么说明l到r的每个数的第j