Codeforces Round #310 (Div. 1)B,C,D(set+线段树)

B. Case of Fugitive

Andrewid the Android is a galaxy-famous detective. He is now chasing a criminal hiding on the planet Oxa-5, the planet almost fully covered with water.

The only dry land there is an archipelago of n narrow islands located in a row. For more comfort let’s represent them as non-intersecting segments on a straight line: island i has coordinates [li, ri], besides, ri < li + 1 for 1 ≤ i ≤ n - 1.

To reach the goal, Andrewid needs to place a bridge between each pair of adjacent islands. A bridge of length a can be placed between the i-th and the (i + 1)-th islads, if there are such coordinates of x and y, that li ≤ x ≤ ri, li + 1 ≤ y ≤ ri + 1 and y - x = a.

The detective was supplied with m bridges, each bridge can be used at most once. Help him determine whether the bridges he got are enough to connect each pair of adjacent islands.
Input

The first line contains integers n (2 ≤ n ≤ 2·105) and m (1 ≤ m ≤ 2·105) — the number of islands and bridges.

Next n lines each contain two integers li and ri (1 ≤ li ≤ ri ≤ 1018) — the coordinates of the island endpoints.

The last line contains m integer numbers a1, a2, …, am (1 ≤ ai ≤ 1018) — the lengths of the bridges that Andrewid got.
Output

If it is impossible to place a bridge between each pair of adjacent islands in the required manner, print on a single line “No” (without the quotes), otherwise print in the first line “Yes” (without the quotes), and in the second line print n - 1 numbers b1, b2, …, bn - 1, which mean that between islands i and i + 1 there must be used a bridge number bi.

If there are multiple correct answers, print any of them. Note that in this problem it is necessary to print “Yes” and “No” in correct case.
Sample test(s)
Input

4 4
1 4
7 8
9 10
12 14
4 5 3 8

Output

Yes
2 3 1

Input

2 2
11 14
17 18
2 9

Output

No

Input

2 1
1 1
1000000000000000000 1000000000000000000
999999999999999999

Output

Yes
1

Note

In the first sample test you can, for example, place the second bridge between points 3 and 8, place the third bridge between points 7 and 10 and place the first bridge between points 10 and 14.

In the second sample test the first bridge is too short and the second bridge is too long, so the solution doesn’t exist.

题意:有n个岛,m座桥,如果桥的长度能够满足能架在岛上,并且不超过岛的长度,那么可以,问所有的岛能不能联通起来
思路:每个岛(l,r),应该尽量找大于等于l,并且小于等于r,跟r相差最小的,那么可以对岛进行排序,然后维护一个set,用来找离r最近的是哪座桥。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=200010;
int N,M;
struct A
{
    LL l,r;
    int id;
    bool operator<(const A &a)const
    {
        return l<a.l;
    }
}a[maxn];
pair<LL,int> p[maxn];
set<pair<LL,int>> st;
int ans[maxn];
int main()
{
    scanf("%d%d",&N,&M);
    if(M<N-1){printf("No\n");return 0;}
    LL l,r,ll=0,lr=0;
    N--;
    cin>>ll>>lr;
    for(int i=1;i<=N;i++)
    {
        cin>>l>>r;
        a[i].l=l-lr;
        a[i].r=r-ll;
        a[i].id=i;
        ll=l,lr=r;
    }
    for(int i=1;i<=M;i++)
    {
        cin>>l;
        p[i]=make_pair(l,i);
    }
    sort(a+1,a+1+N);
    sort(p+1,p+1+M);
    for(int j=M,i=N;i>0;i--)
    {
        while(j>0&&p[j].first>=a[i].l)
            st.insert(p[j]),j--;
        set<pair<LL,int>>::iterator it=st.upper_bound(make_pair(a[i].r+1,0));
        if(it==st.begin())
        {
            printf("No\n");
            return 0;
        }
        it--;
        ans[a[i].id]=it->second;
        st.erase(it);
    }
    printf("Yes\n");
    for(int i=1;i<=N;i++)
        printf("%d ",ans[i]);
    printf("\n");
    return 0;
}

C. Case of Chocolate

Andrewid the Android is a galaxy-known detective. Now he does not investigate any case and is eating chocolate out of boredom.

A bar of chocolate can be presented as an n × n table, where each cell represents one piece of chocolate. The columns of the table are numbered from 1 to n from left to right and the rows are numbered from top to bottom. Let’s call the anti-diagonal to be a diagonal that goes the lower left corner to the upper right corner of the table. First Andrewid eats all the pieces lying below the anti-diagonal. Then he performs the following q actions with the remaining triangular part: first, he chooses a piece on the anti-diagonal and either direction ‘up’ or ‘left’, and then he begins to eat all the pieces starting from the selected cell, moving in the selected direction until he reaches the already eaten piece or chocolate bar edge.

After each action, he wants to know how many pieces he ate as a result of this action.
Input

The first line contains integers n (1 ≤ n ≤ 109) and q (1 ≤ q ≤ 2·105) — the size of the chocolate bar and the number of actions.

Next q lines contain the descriptions of the actions: the i-th of them contains numbers xi and yi (1 ≤ xi, yi ≤ n, xi + yi = n + 1) — the numbers of the column and row of the chosen cell and the character that represents the direction (L — left, U — up).
Output

Print q lines, the i-th of them should contain the number of eaten pieces as a result of the i-th action.
Sample test(s)
Input

6 5
3 4 U
6 1 L
2 5 L
1 6 U
4 3 U

Output

4
3
2
1
2

Input

10 6
2 9 U
10 1 U
1 10 U
8 3 L
10 1 L
6 5 U

Output

9
1
10
6
0
2

Note

Pictures to the sample tests:
这里写图片描述
The pieces that were eaten in the same action are painted the same color. The pieces lying on the anti-diagonal contain the numbers of the action as a result of which these pieces were eaten.

In the second sample test the Andrewid tries to start eating chocolate for the second time during his fifth action, starting from the cell at the intersection of the 10-th column and the 1-st row, but this cell is already empty, so he does not eat anything.

题意:上三角,每次可以从副对角线上选一个点,然后选择向上或者向左走,问每次能走多少个格子,走过的不能再走
思路:首先离散化,我是对x坐标离散的,然后维护一个左边界限和上边界线,每次之需要查询,然后进行更新,更新的时候要注意,是更新这个点和他能走到的那个格子的x坐标之间的副对角线上的点

#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
int X[maxn];
int N,M;
struct node
{
    int x,y;
    char d[5];
}op[maxn];
bool vis[maxn];
struct IntervalTree
{
    int up[maxn<<2];
    int down[maxn<<2];
    int set1[maxn<<2];
    int set2[maxn<<2];
    void build(int o,int l,int r)
    {
        up[o]=down[o]=0;
        set1[o]=set2[o]=0;
        if(l==r)return ;
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
    }
    void update(int o,int l,int r,int q1,int q2,int x,bool f)
    {
        if(q1<=l&&r<=q2)
        {
            if(f&&x>up[o])set1[o]=x,up[o]=x;
            else if(!f&&x>down[o]) set2[o]=x,down[o]=x;
            return ;
        }
        pushdown(o,f);
        int mid=(l+r)>>1;
        if(q1<=mid)update(o<<1,l,mid,q1,q2,x,f);
        if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,x,f);
    }
    void pushdown(int o,bool f)
    {
        if(f)
        {
            if(set1[o])
            {
                if(set1[o]>set1[o<<1])
                    set1[o<<1]=set1[o],up[o<<1]=set1[o];
                if(set1[o]>set1[o<<1|1])
                    set1[o<<1|1]=set1[o],up[o<<1|1]=set1[o];
                set1[o]=0;
            }
        }
        else
        {
            if(set2[o])
            {
                if(set2[o]>set2[o<<1])
                    set2[o<<1]=set2[o],down[o<<1]=set2[o];
                if(set2[o]>set2[o<<1|1])
                    set2[o<<1|1]=set2[o],down[o<<1|1]=set2[o];
                set2[o]=0;
            }
        }
    }
    int query(int o,int l,int r,int pos,bool f)
    {
        if(l==r)return f?up[o]:down[o];
        pushdown(o,f);
        int mid=(l+r)>>1;
        if(pos<=mid)return query(o<<1,l,mid,pos,f);
        return query(o<<1|1,mid+1,r,pos,f);
    }
}tree;
int main()
{
    scanf("%d%d",&M,&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%d%d%s",&op[i].y,&op[i].x,op[i].d);
        X[i]=op[i].x;
    }
    sort(X+1,X+1+N);
    tree.build(1,1,N);
    for(int i=1;i<=N;i++)
    {
        int tmp=lower_bound(X+1,X+1+N,op[i].x)-X;
        if(vis[tmp]){printf("0\n");continue;}
        vis[tmp]=1;
        if(op[i].d[0]=='U')
        {
            int pos=tree.query(1,1,N,tmp,1);
            int tmp1=lower_bound(X+1,X+1+N,pos)-X;
            if(pos==0)tmp1=0;
            if(tmp1+1<=tmp)tree.update(1,1,N,tmp1+1,tmp,op[i].y,0);
            printf("%d\n",op[i].x-pos);
        }
        else
        {
            int pos=tree.query(1,1,N,tmp,0);
            int tmp1=lower_bound(X+1,X+1+N,1+M-pos)-X;
            if(pos==0)tmp1=N+1;
            if(tmp1-1>=tmp)tree.update(1,1,N,tmp,tmp1-1,op[i].x,1);
            printf("%d\n",op[i].y-pos);
        }
    }
    return 0;
}

D. Case of a Top Secret
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Andrewid the Android is a galaxy-famous detective. Now he is busy with a top secret case, the details of which are not subject to disclosure.

However, he needs help conducting one of the investigative experiment. There are n pegs put on a plane, they are numbered from 1 to n, the coordinates of the i-th of them are (xi, 0). Then, we tie to the bottom of one of the pegs a weight on a tight rope of length l (thus, its coordinates will be equal to (xi,  - l), where i is the number of the used peg). Then the weight is pushed to the right, so that it starts to rotate counterclockwise. At the same time, if the weight during rotation touches some of the other pegs, it then begins to rotate around that peg. Suppose that each peg itself is very thin and does not affect the rope length while weight is rotating around it.

More formally, if at some moment the segment of the rope contains one or more pegs in addition to the peg around which the weight is rotating, the weight will then rotate around the farthermost one of them on a shorter segment of a rope. In particular, if the segment of the rope touches some peg by its endpoint, it is considered that the weight starts to rotate around that peg on a segment of the rope of length 0.

At some moment the weight will begin to rotate around some peg, without affecting the rest of the pegs. Andrewid interested in determining the number of this peg.

Andrewid prepared m queries containing initial conditions for pushing the weight, help him to determine for each of them, around what peg the weight will eventually rotate.
Input

The first line contains integers n and m (1 ≤ n, m ≤ 2·105) — the number of pegs and queries.

The next line contains n integers x1, x2, …, xn ( - 109 ≤ xi ≤ 109) — the coordinates of the pegs. It is guaranteed that the coordinates of all the pegs are distinct integers.

Next m lines contain the descriptions of the queries of pushing the weight, each consists of two integers ai (1 ≤ ai ≤ n) and li (1 ≤ li ≤ 109) — the number of the starting peg and the length of the rope.
Output

Print m lines, the i-th line should contain the number of the peg around which the weight will eventually rotate after the i-th push.
Sample test(s)
Input

3 2
0 3 5
2 3
1 8

Output

3
2

Input

4 4
1 5 7 15
1 4
2 15
3 16
1 28

Output

2
4
3
1

Note

Picture to the first sample test:

Picture to the second sample test:

Note that in the last query weight starts to rotate around the peg 1 attached to a rope segment of length 0.
题目:给n个挂点,m个重锤,第i个重锤初始挂在第ai个挂点上,挂绳长度为leni,初始向右摆动,刮到一个重锤后会折返,问最后挂在哪个重锤上

思路(转自:这里写链接内容):每次二分找位置,记录路径,如果是A−A−A就输出答案,如果是A−B−A就取模,这样不超过log2len次挂绳的长度就会变为0
复杂度O(m∗log2n∗log2len)

#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
int pos[maxn],A[maxn],id[maxn];
int N,Q;
int st[maxn];
bool cmp(int x,int y)
{
    return pos[x]<pos[y];
}
int main()
{
    scanf("%d%d",&N,&Q);
    for(int i=1;i<=N;i++)scanf("%d",&A[i]),pos[i]=A[i],id[i]=i;
    sort(id+1,id+1+N,cmp);
    sort(pos+1,pos+1+N);
    int x,len;
    while(Q--)
    {
        scanf("%d%d",&x,&len);
        int top=0;
        int cur=lower_bound(pos+1,pos+1+N,A[x])-pos;
        st[top=1]=cur;
        while(true)
        {
            if(top>=3&&st[top]==st[top-1]&&st[top]==st[top-2])
            {
                printf("%d\n",id[st[top]]);
                break;
            }
            if(top>=3&&st[top]==st[top-2])
                len%=(abs(pos[st[top]]-pos[st[top-1]]))*2;
            int next_pos;
            if(top&1)next_pos=upper_bound(pos+1,pos+1+N,pos[cur]+len)-pos-1;
            else next_pos=lower_bound(pos+1,pos+1+N,pos[cur]-len)-pos;
            len=len-abs(pos[cur]-pos[next_pos]);
            cur=next_pos;
            st[++top]=cur;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值