做题记录整理树状数组3 P3960 [NOIP2017 提高组] 列队(2022/9/29)

P3960 [NOIP2017 提高组] 列队
及其抽象的题目,由于实力不足
几乎相当于照着题解打了一遍
以后回来看得再做一遍

#include<bits/stdc++.h>
#define for1(i,a,b) for(int i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;
const ll  inf=600010;
struct node{
   ll x;
   ll y;
   ll id;
   bool flag;
}dl[300050];
vector<ll> v[300050];
vector<ll> a;
ll n,m,q,len,len2,st,tj;
ll p[2*300050];
ll t1[2*300050],t2[2*300050];

ll lb(ll x)
{
   return x&-x;
}

void xg(ll x,ll y,ll *t)
{
   while(x<=inf)
   {
       t[x]+=y; 
	   x+=lb(x);
   }
}

ll cx(ll x,ll *t)
{
   ll re = 0;
   while(x > 0)
    {
        re+=t[x];
	    x-=lb(x);
    }
   return re;
}

bool cmp1(node x,node y)
{
   if(x.x!=y.x)
       return x.x<y.x;
       return x.id<y.id;
}

bool cmp2(node x,node y)
{
   return x.id<y.id;
}

int main()
{
   scanf("%lld%lld%lld",&n,&m,&q); 
   len=n;
   for1(i,1,q)
   {
       scanf("%lld%lld",&dl[i].x,&dl[i].y);
       dl[i].id=i;
	   dl[i].flag=false;
   }
   
   for1(i,1,n)
       p[i]=i*m*1ll;
   for1(i,1,inf)
       t1[i]=t2[i]=lb(i);
       
   sort(dl+1,dl+1+q,cmp1); 
   st=1;tj=1;
   while(st <= q)
   {
       while(tj<q&&dl[st].x==dl[tj+1].x) tj++;
       a.clear();len2=m;
       
       for1(i,st,tj)
	   {
           if(dl[i].y==m)
		   {
               dl[i].flag=true; 
			   continue;
           }
           ll l=1,r=len2;
           ll mid;
           while(l < r)
		   {
		   	    mid=(l+r)>>1;
               if(cx((l+r)/2,t2)>=dl[i].y)
			   
                   r=mid;
               else
                   l=mid+1;
               
           }
           xg(l,-1,t2);
		    a.push_back(l); 
			dl[i].y=l; 
			len2++;
       }
       for(ll i=0;i<a.size();i++)
           xg(a[i],1,t2);
       st=tj+1;
   }
   sort(dl+1,dl+1+q,cmp2);

   for1(i,1,q)
   {
       ll ans;
       if(!dl[i].flag)
           if(dl[i].y<m)
		   {
               ans=1ll*(dl[i].x-1)*m+dl[i].y;
               printf("%lld\n",ans);
           }
		   else
		   {
               dl[i].y=dl[i].y-m;
               ans=v[dl[i].x][dl[i].y];
               printf("%lld\n",ans);
           }
    
       

       ll l=1,r=len;
       ll mid;
       while(l<r)
	   {
	   	    mid=(l+r)>>1;
           if(cx(mid,t1)>=dl[i].x)
               r=mid;
           else
               l=mid+1;
           
       }
       xg(l,-1,t1);
       if(!dl[i].flag)
           v[dl[i].x].push_back(p[l]);
       else
	   {
           ans=p[l];
           printf("%lld\n",ans);
       }
        p[++len]=ans;
   }
   return 0;
}
posted @ 2022-09-29 21:52  yyx525jia  阅读(44)  评论(0)    收藏  举报