5478. [NOIP2017グループ一致公式パレードを改善]

タイトル説明

シルビアは、学習の女の子の愛です。
いくつかの時間前、シルビアは軍事訓練の学校に通りました。軍事的必要性が正方形に立つために、我々はすべて知っている、など。学生m×n個あるシルビア広場は、行列の行の数は列の数をm、nとします。
投与を容易にするために、トレーニングインストラクターの開始時に、バックに前方によれば、数(以下の例を参照)上でコンパイル1から正方形に左N×M個の順です。すなわち: - ×M +学生番号の最初のi行の第j列(1、I)は 、J。
しかし、実際には、とき四角、学生は多くの場合、残して、物事の様々なを持っているので。一日では、Q個の合計は、このようなイベントを残すために起こりました。各イベントは、(Y、Z)(1≤x≤n、数に残すことができ 1≤y≤m) 記述、xはチームを離れる学生の行Y列を表します。
学生が残した後、チームは空きがあります。:きちんとしたチームには、順番に、このようなインストラクターは、2つの命令発行の
左に1ドレスを。そして、最初の列は、すべての学生が左のギャップを埋めるために、そのまま残ります。この命令を見つけることは困難後、ギャップは、最初の行のm番目の列をxは。
2.一緒に先読み。そして、最初の行には、前方に空席を埋めるために、すべての学生そのまま残ります。困難後、この命令、第n行m列の第1のギャップを検索します。
インストラクターの規定はチームを離れる同時に2人の以上の生徒を持つことはできません。それは次のままにする元学生が再結合学生の後にバンドを脱退しました。したがって、その後、再結合を残す学生、m列n行目の唯一のランクの各ギャップ、自然にこのポジションを埋めるために学生。
駅前は本当に退屈しているので、シルビアは休暇を望んでいるので、すべてのイベント、チームは去る学生数が計算されます。
注:各学生数は、オーダーしていない可能性があり、学生の平方数の事件の後にチームを残して、変更のイベントの発生を残すことはありません。

トピック分析

難しい質問。
しかし、我々は、全体のプロセスは、2つの動作モードにまとめることができることを見出した:
1.シーケンスからkの数を特定し、削除します。
バックに追加シーケンス番号を削除します。2.。
だから我々は、解決するには、N + 1柯ツリーラインを使用することができます。
最初のn行ツリーはのM-1列目の各列のために維持される
N + 1-M-ツリーメンテナンスカラム。
キーがある30万*30万Zezheng?
それだけで解決するには、ダイナミックポイントで開くことができます。
オープンポイントを動的にするには?コードで自分の見て、それを学ぶための方法。

コード

#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef long long ll;
struct node
{
    int x,y;
}a[310000];
struct tree
{
    int lc,rc;ll c;
}tr[6100000];int tail[310000],root[310000];
int tot=0;int size[6100000];
void insert(int &now,int l,int r,int k,ll num)
{
    if(now==0) now=++tot;
    if(l==r)
    {
        tr[now].c=num;
        size[now]=0;
        return ;
    }
    int mid=(l+r)/2;
    if(k<=mid) insert(tr[now].lc,l,mid,k,num);
    else insert(tr[now].rc,mid+1,r,k,num);
    size[now]=size[tr[now].lc]+size[tr[now].rc];
}
ll findkth(int &now,int l,int r,int k,int &ans)
{
    if(now==0) now=++tot;
    if(l==r)
    {
        ans=l;
        ll temp=tr[now].c;tr[now].c=0;
        size[now]=1;
        return temp;
    }
    int mid=(l+r)/2;ll temp;
    if(mid-l+1-size[tr[now].lc]>=k)
    {
        temp=findkth(tr[now].lc,l,mid,k,ans);
    }
    else
    {
        temp=findkth(tr[now].rc,mid+1,r,k-(mid-l+1-size[tr[now].lc]),ans);
    }
    size[now]=size[tr[now].lc]+size[tr[now].rc];
    return temp;
}
int main()
{
    ll n,m,q;
    scanf("%lld%lld%lld",&n,&m,&q);
    for(int i=1;i<=n;i++) tail[i]=m-1;
    tail[n+1]=n;
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&a[i].x,&a[i].y);
        if(a[i].y==m)
        {
            int temp2;
            ll temp=findkth(root[n+1],1,n+q,a[i].x,temp2);
            if(temp2<=n) temp=temp2*m;
            printf("%lld\n",temp);
            insert(root[n+1],1,n+q,++tail[n+1],temp);
        }
        else
        {
            int temp2;
            ll temp=findkth(root[a[i].x],1,m+q,a[i].y,temp2);
            if(temp2<m) temp=m*(a[i].x-1)+temp2;
            printf("%lld\n",temp);
            insert(root[n+1],1,n+q,++tail[n+1],temp);
            temp=findkth(root[n+1],1,n+q,a[i].x,temp2);
            if(temp2<=n) temp=temp2*m;
            insert(root[a[i].x],1,m+q,++tail[a[i].x],temp);
        }
    }
    return 0;
}
公開された58元の記事 ウォン称賛12 ビュー8581

おすすめ

転載: blog.csdn.net/fengqiyuka/article/details/78635585