gym102452 I Incoming Asteroids (2019-2020 ICPC Asia Hong Kong Regional Contest) 抽屉原理

题意

(n)个位置可以进行观测。第一种操作可以在(k (kle3))个位置添加摄像头,目标是收集(y)个单位的观测值;第二种操作是在第(x)个位置所有的摄像头产生了(y)个单位的观测值,输出该次操作使得操作一首次达到目标的数量和编号。强制在线。

思路

考虑(k)的值比较少,并由抽屉原理,我们可以对每个位置建立一个数据结构,插入操作一目标的(frac1k),当这个位置的观测值的增长超过插入值时,取出并更新操作一的目标并重新插入。这样每次取出操作一的目标至少减少到原来的(frac{k-1}k),对于每个操作一最多取出(log_{frac{k-1}k}(y))次,总复杂度(O(m*log m*log y))

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli;
#define mp make_pair
const int maxn=2e5+5;
const int maxm=2e5+5;
ll v[maxn];
priority_queue<pli,vector<pli>,greater<pli> >st[maxn];

int Q[maxm][4];
int Y[maxm],D[maxm];
int vis[maxm];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    
    int op,x,k,q,last=0,cnt=0;
    ll y;
    while(m--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%lld%d",&y,&k);
            y=y^last;

            ++cnt;
            Q[cnt][0]=k;
            Y[cnt]=D[cnt]=y;
            for(int kk=1;kk<=k;kk++)
            {
                scanf("%d",&q);
                q=q^last;
                Q[cnt][kk]=q;
                Y[cnt]+=v[q];
            }
            for(int kk=1;kk<=k;kk++)
                st[Q[cnt][kk]].push(mp(v[Q[cnt][kk]]+(D[cnt]+k-1)/k,cnt));

        }
        else //op==2
        {
            scanf("%d%d",&x,&y);
            x=x^last;
            y=y^last;

            vector<int>ans;
            v[x]+=y;
            while(!st[x].empty() && st[x].top().first<=v[x])
            {
                ll tmp=st[x].top().first;
                int i=st[x].top().second;
                st[x].pop();
                if(vis[i])continue;

                D[i]=Y[i];
                for(int kk=1;kk<=Q[i][0];kk++)
                    D[i]-=v[Q[i][kk]];

                if(D[i]<=0)
                {
                    ans.push_back(i);
                    vis[i]=1;
                }
                else
                {
                    k=Q[i][0];
                    for(int kk=1;kk<=k;kk++)
                        st[Q[i][kk]].push(mp(v[Q[i][kk]]+(D[i]+k-1)/k,i));
                }
            }
            sort(ans.begin(),ans.end());
            printf("%d",last=(int)ans.size());
            for(int i=0;i<ans.size();i++)
                printf(" %d",ans[i]);
            printf("
");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/intmian/p/13639732.html