[Gdgzezoi]問題A:玩具パズル

説明

南小さなかわいいおもちゃの悪役を持って、彼らは別の職業を持っています。

ある日、これらのおもちゃ南メガネ隠れ悪役少し。小さな南のおもちゃは、人々は、いくつかのサークルの外に直面し、それらのいくつかは、円に直面して、小さな円の中に身を寄せ合った見つけました。図は次のとおりです。

その後、歌手は小さな南のパズルに語った:「メガネは、左の数に隠され、右からが悪役最初の二つのおもちゃの私の3件のおもちゃ悪役番号1つのおもちゃの悪役を残しました。」

円おもちゃの悪役に直面し、それは時計回りに残っている、右:小さな南は左と内側と外側に反対の右方向のおもちゃの悪役ので直面悪役パズルのおもちゃは、重要であることがわかりましたそれは反時計回りであり、部外のおもちゃの悪役のために、それは左に反時計回りで、右は右回りです。

カウントながら、おもちゃの悪役を識別するために苦労小南側:

「北朝鮮は歌手で、左射手から第三です。

「右1から外側に向かってアーチャーは、思想家です。

「考える人は外側に、左から2番目は作家です。

「だからライターのガラスはここに隠されました!」

けれども成功はメガネを回復したが、小さな南は保証されていません。より多くのおもちゃは、次の彼の眼鏡を隠し悪役、またはパズルの長い部分の長さがある場合、彼は眼鏡を見つけることができない場合があります。問題を解決するために、彼はそんなにトラブルがあるだろうだから、悪役のおもちゃの数を減少させるために、お互いを殺し、彼のおもちゃが互いに戦う悪役せることを決めました。

N小さな南悪役おもちゃの合計、各おもちゃは、悪役の戦いを持っている、いくつかの小さなおもちゃを置く南悪役は赤く染め(すべてがブルーに染色、ある投票、することはできません。すべては、赤く染めたことができます)、残りは(それらの一方は空であってもよい)ので、赤側と青側が互いに戦うために、染色された青色です。

同党の2つの戦いのおもちゃの悪役とのギャップが大きすぎる場合には、それらの間に矛盾があります。彼のおもちゃは、悪役の間で効果的に悪役のおもちゃの数を減少させるために、望ましい小さな南は可能矛盾限り生成します。したがって、異なる戦闘レッドおもちゃの悪役のいずれか2つの間の差がより大きいか又はAの所定の数に等しくなければならず、異なる戦闘青色玩具悪役のいずれか2つの間の差がより大きくまたは別の所定の数に等しくなければなりません。 B.

小さな南の可能な染色プロトコルは、とても同じ党のおもちゃの悪役は、いずれか2つの間の矛盾を持っていることをどのくらい知ってほしいです。あなたは彼がすべての可能なシナリオの合計数をカウント役立つプログラムを書くことがあり、値が+ 7 109を法。

入力

最初の行の入力は、3つの数字N、A、Bを含有します
次のラインNは、i番目の行は、AI整数含まi番目戦闘悪役玩具を表します。

出力

値は、出力染色プロトコル109 + 7の数を法。
サンプル入力

サンプル入力1

5 3 7
1
3
6
9
12

サンプル入力2

7 5 3
0
2
4
7
8
11
15

サンプル入力3

8 2 9
3
4
5
13
15
22
26
32

サンプル入力4

3 3 4
5
6
7
サンプル出力

サンプル出力1

5

サンプル出力2

4

サンプル出力3

13

サンプル出力4

0

ヒント

最初のサンプルでは、​​染色プロトコルの5種類についてある、赤悪役セットはX、Y、青色であることに注意。

  1. X = {1,6,9,12}、Y = {3}
  2. X = {1,6,9}、Y = {3,12}
  3. X = {3,6,9,12}、Y = {1}
  4. X = {3,6,9}、Y = {1,12}
  5. X = {3,6,12}、Y = {1,9}

データ範囲:
1≤N≤105
1≦、B≤1018
0≤ai≤1018
AI <AI + 1(1≤i<N)。

サブタスク30ポイント、会う1≤N≤2000があります。

思考

まずO(N-考える2)プラクティス:

便宜上、我々は、A0 =-∞を設定しました

提供FM、I、J(M∈{X、Y}、1≤i≤nは、0≤jは<i)はiとSjには、最後のプログラム要素Mの数ではない、良好な分割S1を示し⋯

私が転送する方法、J、⋯1、良いFX、1⋯I、J年度と考えられてきましたか?

①もしAI + 1-ai≥Aに、Si + 1はXに配置することができ、その後、FX、I + 1,0⋯I-1 = FX、I、0⋯I-1

そうでなければ1は、I + 1,0、X、FXに沿って配置することができない⋯I-1 = 0 + AI、愛

②显然fY,i+1,i=∑j=0i−1[ai+1−Sj≥B]fX,i,j

FY同様の治療

最終的な答えは、Σiは= 0N-1fXであり、nは、I +Σiは= 0N-1FY、N、I

最適化を考えてみましょう

最初の昇順にソート

インクリメントされているので、これを満たすには、我々は、2つのポイントと右端を見つけて間隔とセグメントツリーとを決定できるように、+ 1-aj≥BがSjには、接頭辞の一部でなければならない愛

他の転送セグメントツリーは、単一点の更新に相当します

コード

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
const int N=1e5+77;
int sumx[N*4],sumy[N*4],lazx[N*4],lazy[N*4],*laz,*sum,n;
ll a[N];
void pushdown(int x)
{
    if(laz[x])
    {
        laz[x<<1]=laz[x<<1|1]=1;
        sum[x<<1]=sum[x<<1|1]=0;
        laz[x]=0;
    }
}
int query(int st,int ed,int l,int r,int x)
{
    if(st<=l&&r<=ed)return sum[x];
    pushdown(x);
    int mid=(l+r)>>1,ans=0;
    if(st<=mid)ans=(ans+query(st,ed,l,mid,x<<1))%mod;
    if(mid<ed)ans=(ans+query(st,ed,mid+1,r,x<<1|1))%mod;
    return ans;
}
void add(int pos,int v,int l,int r,int x)
{
    if(l==r)
    {
        sum[x]=(sum[x]+v)%mod; return;
    }
    pushdown(x);
    int mid=(l+r)>>1;
    if(pos<=mid) add(pos,v,l,mid,x<<1);
    else add(pos,v,mid+1,r,x<<1|1);
    sum[x]=(sum[x<<1]+sum[x<<1|1])%mod;
}
int queryx(int st,int ed)
{
    laz=lazx; sum=sumx;
    return query(st,ed,0,n-1,1);
}
void addx(int pos,int v)
{
    laz=lazx; sum=sumx;
    add(pos,v,0,n-1,1);
}
int queryy(int st,int ed)
{
    laz=lazy; sum=sumy;
    return query(st,ed,0,n-1,1);
}
void addy(int pos,int v)
{
    laz=lazy; sum=sumy;
    add(pos,v,0,n-1,1);
}
int main()
{
    ll A,B;
    scanf("%d%lld%lld",&n,&A,&B);
    for(int i=1; i<=n; i++)scanf("%lld",&a[i]);
    sort(a+1,a+n+1);
    a[0]=-4223372036854775807ll;
    addx(0,1); addy(0,1);
    for(int i=1; i<n; i++)
    {
        int l=0,r=i-1,x=0;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(a[i+1]-a[mid]>=B) x=mid,l=mid+1;else r=mid-1;
        }
        int t1=queryx(0,x);
        l=0; r=i-1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(a[i+1]-a[mid]>=A) x=mid,l=mid+1;else r=mid-1;
        }
        int t2=queryy(0,x);
        if(a[i+1]-a[i]<A)
        {
            sumx[1]=0; lazx[1]=1;
        }
        if(a[i+1]-a[i]<B)
        {
            sumy[1]=0; lazy[1]=1;
        }
        addy(i,t1); addx(i,t2);
    }
    printf("%d",(queryx(0,n-1)+queryy(0,n-1))%mod);
}
703元記事公開 ウォンの賞賛392 ビューに14万+を

おすすめ

転載: blog.csdn.net/Eric1561759334/article/details/100835844