CodeForces 596C Wilbur and Points

先对n个点分类,然后按题意要求构造,构造的时候判断这个点的右上方之前是否有点,判断可以用线段树来操作。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=200000+10;
vector<int>g[2*maxn],FX,FY;
int w[maxn];
struct X
{
    int x,y,id;
}s[maxn],tmp[maxn];
int n,Max;
int segtree[2*maxn];
bool cmp(const X&a,const X&b)  {return a.x<b.x;}
void quary(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) {Max=max(Max,segtree[rt]); return ;}
    int m=(l+r)/2;
    if(L<=m) quary(L,R,l,m,2*rt);
    if(R>m) quary(L,R,m+1,r,2*rt+1);
}
void update(int pos,int val,int l,int r,int rt)
{
    if(l==r&&l==pos) { segtree[rt]=val; return; }
    int m=(l+r)/2;
    if(pos<=m) update(pos,val,l,m,2*rt);
    else update(pos,val,m+1,r,2*rt+1);
    segtree[rt]=max(segtree[2*rt],segtree[2*rt+1]);
}
int main()
{
    scanf("%d",&n); FX.clear(); FY.clear();
    for(int i=1;i<=n;i++) scanf("%d%d",&s[i].x,&s[i].y);
    for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    sort(s+1,s+1+n,cmp);
    for(int i=1;i<=n;i++) g[s[i].y-s[i].x+200000].push_back(i);
    bool fail=0; map<int,int>h; h.clear();
    memset(segtree,-1,sizeof segtree);
    for(int i=1;i<=n;i++)
    {
        if(h[w[i]]==g[w[i]+200000].size()) {fail=1;break;}
        int id=g[w[i]+200000][h[w[i]]];
        Max=-1; quary(s[id].x,100000,0,100000,1);
        if(Max>=s[id].y){fail=1;break;}
        update(s[id].x,s[id].y,0,100000,1);
        int tmpx=s[id].x,tmpy=s[id].y;
        FX.push_back(tmpx); FY.push_back(tmpy);  h[w[i]]++;
    }
    if(fail==0)
    {
        printf("YES\n");
        for(int i=0;i<FX.size();i++) printf("%d %d\n",FX[i],FY[i]);
    }
    else printf("NO\n");
    return 0;
}
时间: 2024-10-06 00:50:10

CodeForces 596C Wilbur and Points的相关文章

Codeforces Round #331 (Div. 2)C. Wilbur and Points

题目解释:n个点对,n个数,要求求出是否存在一个增序列满足答案,并输出. (集合规则:如果(x,y)在集合里,那么(0,0)到(x,y-1),(x-1,y)也在集合里 输入的时候也是) 首先怎么暴力怎么来,我们先对n个点对进行分类(根据差值分类),然后每一类分别从小到大排序.然后目前的解就是一次填充n个数,因为小的肯定在大的前面被填充,否则就不符合集合的定义. 然后进行判断,因为数据点没有突变,只要严格意义上不比前一个数大就行,因为都是连续的数据段. #include<cstdio> #inc

Codeforces 850A - Five Dimensional Points(暴力)

原题链接:http://codeforces.com/problemset/problem/850/A 题意:有n个五维空间内的点,如果其中三个点A,B,C,向量AB,AC的夹角不大于90°,则点A是"bad"的否则是"good".题目让我们输出good的点. 思路:从2,3维空间超过5,7个点时不存在"good"的点,可以简单推知五维空间内,超过11个点时不存在"good"的点,那么点数小于11时暴力,大于11时输出0. 其

CodeForces 596B Wilbur and Array

简单题,一个一个操作,最后就是答案. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; long long a[200000+10]; long long pre; int n; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf(

CodeForces 596A Wilbur and Swimming Pool

水题. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; struct X { int x,y; }s[5],tmp[5]; int n; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&am

CodeForces 251A. Points on Line(数学 lower_bound )

题目链接:http://codeforces.com/problemset/problem/251/A Little Petya likes points a lot. Recently his mom has presented him n points lying on the line OX. Now Petya is wondering in how many ways he can choose three distinct points so that the distance be

Codeforces 19D Points 线段树+set

题目链接:点击打开链接 线段树维护y值大于val的最小x值 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> #include <map> #include <set> #include <math.h> using namespace std; #define inf

Codeforces 347B - Fixed Points

题意:给定一个序列,现有一种操作:两个数的位置互换.问最多操作一次,序列 [元素位置i]  与 [元素Ai] 相等的最多个数? 根据题意,最多个数为 : [操作之前[元素位置i]  与 [元素Ai] 相等的个数] +  [调换两个 [元素位置i]  与 [元素Ai] 不相等 的元素 使某个 [元素位置i]  与 [元素Ai] 相等的个数]. 举个例子: 0 1 2 4 3 这个序列,调换后面两个元素,正好使每个 [元素位置i]  与 [元素Ai] 相等. 也就是说,调换的时候,不用考虑 [元素位

Codeforces Round #245 (Div. 2) A - Points and Segments (easy)

水到家了 #include <iostream> #include <vector> #include <algorithm> using namespace std; struct Point{ int index, pos; Point(int index_ = 0, int pos_ = 0){ index = index_; pos = pos_; } bool operator < (const Point& a) const{ return p

Codeforces 19D Points(树状数组)

题目链接:Codeforces 19D Points 题目大意:N中操作,每次添加一个点,或者删除一个点,以及找到给定x,y坐标最近的一个坐标,并且保证xi,yi在x,y的右上角. 解题思路:这题的解法还是很机智的. y坐标离散化,然后树状数组的每个单位用一个set代替,set记录的是点集. 剩下的操作就像树状数组一样,每次添加就等于是+w的操作,移除就等于是-w,只是w是一个点,那么find操作就等于是在sum操作生成的点集中二分查找. #include <cstdio> #include