luogu 3960 列队

noip2017 D2T3 列队 某zz选手当时直接放弃了写了50还写错了

题目大意:

有一个n行m列的方阵,第i行j列的点编号为(i-1)m+j

每次把第x行y列的点拿出来,然后把这一行它之后的点都向左推,把最后一列x行之后的点都向上推

然后把拿出来的点放到最后一个位置,询问这个点的编号

思路:

因为n+q并不大 可以动态开点每行维护一个权值线段树 并对最后一行单独维护

对于新进来的点使用vector维护

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 300100
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int n,m,q,rt[MAXN],ls[MAXN*20],rs[MAXN*20],sum[MAXN*20],sz;
21 ll ans[MAXN<<1];
22 vector <ll> vec[MAXN];
23 int query(int &k,int l,int r,int x)
24 {
25     if(!k) k=++sz,sum[k]=r-l+1;
26     sum[k]--;
27     if(l==r) return l;
28     int mid=l+r>>1,sl=ls[k]?sum[ls[k]]:mid-l+1;
29     if(x<=sl) query(ls[k],l,mid,x);
30     else query(rs[k],mid+1,r,x-sl);
31 }
32 int main()
33 {
34     n=read(),m=read(),q=read();int a,b,res;
35     for(int i=1;i<=n;i++) ans[i]=1ll*i*m;
36     for(int i=n+1;i<=n+q;i++)
37     {
38         a=read(),b=read();
39         if(b==m) ans[i]=ans[query(rt[0],1,n+q,a)];
40         else 
41         {
42             res=query(rt[a],1,m+q,b);
43             if(res<m) ans[i]=(a-1ll)*m*1ll+res;
44             else ans[i]=vec[a][res-m];
45             vec[a].push_back(ans[query(rt[0],1,n+q,a)]);
46         }
47         printf("%lld\n",ans[i]);
48     }
49 }
View Code

猜你喜欢

转载自www.cnblogs.com/yyc-jack-0920/p/9757090.html