Gym 100971D Laying Cables

要求找出每个a[i],找到离他最近而且权值比它大的点,若距离相同,输出权利最大的那个

我的做法有点复杂,时间也要500+ms,因为只要时间花在了map上。

具体思路是模拟一颗树的建立过程,对于权值最大的那个,必须是-1,次大的那个,必须是pos_peo[mx];就是最大人口的节点id、

然后维护一个单调的序列,记录当前有多少个位置加入了树。用个set保证单调性。小到大

把结构体按人口排序大到小,枚举没个城市,这样保证加入后,后面加入的直接找位置最短即可,人口最对的bigger than now的。

二分一个位置,> now.pos的,枚举它左右,选择即可。注意就是当距离相同的时候,还要再判断一次。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 200000 + 50;
map<int,int>pos_peo;
map<int,int>pos_pos;
struct data {
    int pos,peo;
} a[maxn],b[maxn];
int ans[maxn];

struct cmp1 {
    bool operator()(int a,int b) {
        return a < b; //
    }
};
bool cmp2 (data a,data b)
{
    return a.peo > b.peo;
}
set<int,cmp1>SS;
void work ()
{
    int n;
    scanf ("%d",&n);
    int mx = -inf;
    for (int i=1; i<=n; ++i) {
        scanf ("%d%d",&a[i].pos,&a[i].peo);
        b[i].pos=a[i].pos;
        b[i].peo=a[i].peo;
        pos_peo[a[i].peo] = i; //id
        pos_pos[a[i].pos] = i;
        mx = max(mx,a[i].peo);
    }
    if (n==1) {
        printf ("-1\n");
        return ;
    }
    ans[pos_peo[mx]] = -1;
    int sec = -inf;
    for (int i=1; i<=n; ++i) {
        if (sec < a[i].peo && a[i].peo != mx)
            sec = a[i].peo;
    }
    ans[pos_peo[sec]] = pos_peo[mx];

    SS.insert(a[pos_peo[mx]].pos);
    SS.insert(a[pos_peo[sec]].pos);

    sort (a+1,a+1+n,cmp2); // peo up to low

    set<int>::iterator it;
    for (int i=3; i<=n; ++i) {
        int val = a[i].pos;
        int ppeo = a[i].peo;
        it = SS.lower_bound(val);
        int t1 = inf,t2 = inf;
        if (it == SS.begin()) { //在开头
            ans[pos_peo[a[i].peo]] = pos_pos[*it];
        } else if (it == SS.end()) { //在末尾
            it --;
            ans[pos_peo[a[i].peo]] = pos_pos[*it];
        } else {
            int tt1 = *it;
            t1 = abs(val - (*it));
            it--;
            int tt2 = *it;
            t2 = abs(val - (*it));
            if (t1 < t2) {
                ans[pos_peo[a[i].peo]] = pos_pos[tt1];
            } else if (t1 > t2) {
                ans[pos_peo[a[i].peo]] = pos_pos[tt2];
            } else { //xiangdeng
                int id2 = pos_pos[tt1];
                int id1 = pos_pos[tt2];
                int cut2 = abs(b[id2].peo - ppeo);
                int cut1 = abs(b[id1].peo - ppeo);
                if (cut2 > cut1) {
                    ans[pos_peo[a[i].peo]] = pos_pos[tt1];
                } else {
                    ans[pos_peo[a[i].peo]] = pos_pos[tt2];
                }
            }
        }
        SS.insert(a[i].pos);
    }
    for (int i=1; i<=n; ++i) {
        printf ("%d ",ans[i]);
    }
    printf ("\n");
}
int main()
{
#ifdef LOCAL
    freopen("data.txt","r",stdin);
#endif
    work ();
    return 0;
}

时间: 2024-08-03 09:12:51

Gym 100971D Laying Cables的相关文章

Code Forces Gym 100971D Laying Cables(单调栈)

D - Laying Cables Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u One-dimensional country has n cities, the i-th of which is located at the point xi and has population pi, and all xi, as well as all pi, are distinct. Whe

Gym 100971D Laying Cables 单调栈

Description One-dimensional country has n cities, the i-th of which is located at the point xi and has population pi, and all xi, as well as all pi, are distinct. When one-dimensional country got the Internet, it was decided to place the main server

CodeForces Gym 100935D Enormous Carpet 快速幂取模

Enormous Carpet Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Gym 100935D Description standard input/outputStatements Ameer is an upcoming and pretty talented problem solver who loves to solve problems using computers.

B - Average Gym - 101161B 组合数学

http://codeforces.com/gym/101161/attachments 今天被卡常了,其实是自己对组合数技巧研究的不够. 如果是n, m <= 1e5的,然后取模是质数,那么可以用费马小定理. 如果n, m都比较小,那么其实是直接杨辉三角.不用逆元那些. 这题的思路是,枚举每一一个ave,然后总和就是n * ave 相当于方程  x1 + x2 + .... + xn = n * ave中,在0 <= x[i] <= full的情况下,不同解的个数中,使得x[i] ==

Codeforces Gym 100269 Dwarf Tower (最短路)

题目连接: http://codeforces.com/gym/100269/attachments Description Little Vasya is playing a new game named "Dwarf Tower". In this game there are n different items,which you can put on your dwarf character. Items are numbered from 1 to n. Vasya want

CodeForces Gym 101063C 二进制压缩

http://codeforces.com/gym/101063/problem/C 给n个人,m样物品,每个人可以从物品中选择几样.两人选择物品的交集元素个数比上并集元素个数如果大于某个比例即可将两人配对.求配对数. n的范围是1e5,直接比较所有人的选择会TLE,应该将所有选择物品的情况用二进制压缩,m最大是10,情况数目小于2048,可以接受.注意配对总数范围应为long long. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> i

Gym 101246H ``North-East&#39;&#39;(LIS)

http://codeforces.com/gym/101246/problem/H 题意: 给出n个点的坐标,现在有一个乐队,他可以从任一点出发,但是只能往右上方走(包括右方和上方),要经过尽量多的点.输出它可能经过的点和一定会经过的点. 思路: 分析一下第一个案例,在坐标图上画出来,可以发现,他最多可以经过4个点,有两种方法可以走. 观察一下,就可以发现这道题目就是要我们求一个LIS. 首先,对输入数据排一下顺序,x小的排前,相等时则将y大的优先排前面. 用二分法求LIS,这样在d数组中就可

Gym 100712I Bahosain and Digits(开关翻转问题)

http://codeforces.com/gym/100712/attachments 题意: 给出一串数字,每次选择连续的k个数字加上任意数(超过10就取余),最后要使得所有数字都相等,求最大的k. 思路: 开关翻转问题. 算法具体可以参考<挑战程序竞赛>常用技巧篇. 这道题目就是在枚举k的同时再枚举一下最后要转换成的数字即可. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring>

很好的脑洞题:dfs+暴力 Gym - 101128A Promotions

http://codeforces.com/gym/101128 题目大意:给你一个a,b,e,p.有e个点,p条有向边,每条边为(x,y),表示x->y,每次我们都取出一个入度为0的,并且一次性取出来的个数为a(或b).当然,取出来的种类可能有很多种(即一个集合),问,这个集合中有多少个数字是相同的. 第一个输出集合长度为a的,第二个输出集合长度为b的,第三个输出无论如何都无法被取出的个数. 思路:建立正向图和反向图. 定义pair<int, int> interval[i] 表示第i