noip2017列队
#2319. 「NOIP2017」列队
链接
思路
动态开点线段树,详见代码。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e5+7;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,q,rt[N],ls[N*25],rs[N*25],siz[N*25],tot;
vector<ll> pos[N];
int query(int &rt,int l,int r,int k) {
if(!rt) rt=++tot,siz[rt]=r-l+1;
siz[rt]--;
if(l==r) return l;
int mid=(l+r)>>1,now=ls[rt]?siz[ls[rt]]:(mid-l+1);
if(now>=k) return query(ls[rt],l,mid,k);
else return query(rs[rt],mid+1,r,k-now);
}
int main() {
n=read(),m=read(),q=read();
pos[0].push_back(0);
for(int i=1;i<=n;++i) pos[0].push_back(pos[0][i-1]+1LL*m);
for(int i=1;i<=q;++i) {
int x=read(),y=read();
int ans=0;
if(y==m) ans=pos[0][query(rt[0],1,n+q,x)];
else {
int id=query(rt[x],1,n+q,y);
if(id<m) ans=1LL*(x-1)*m+id;
else ans=pos[n][id-m];
pos[x].push_back(pos[0][query(rt[0],1,n+q,x)]);
}
pos[0].push_back(ans);
printf("%lld\n",ans);
}
return 0;
}
思路
80分暴力,part2莫名挂了5分,初测45
代码
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#define ls rt<<1
#define rs rt<<1|1
#define ll long long
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn = 3e5 + 7;
int read() {
int x = 0, f = 1; char s = getchar();
for (; s < '0' || s > '9'; s = getchar()) if (s == '-') f = -1;
for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
return x * f;
}
int n, m, q;
int a[1007][1007];
ll b[maxn];
inline ll calc(int i, int j) {return (ll)(i - 1) *1LL* m + (ll)j;}
void part_1() {
FOR(i, 1, n) FOR(j, 1, m)
a[i][j] = calc(i, j);
FOR(kk, 1, q) {
int x = read(), y = read();
int ans = a[x][y];
printf("%d\n", ans);
FOR(i, y, m - 1) a[x][i] = a[x][i + 1];
FOR(i, x, n - 1) a[i][m] = a[i + 1][m];
a[n][m] = ans;
}
}
vector<ll> h[maxn];
ll l[maxn];
void part_2() {
FOR(i, 1, 300000) h[i].push_back(0);
FOR(i, 1, n) l[i] = calc(i, m);
FOR(kk, 1, q) {
int x = read(), y = read();
ll ans;
if (h[x].size() == 1) {
ans = calc(x, y);
FOR(i, 1, m) h[x].push_back(calc(x, i));
h[x][m]=l[m];
}
ans = h[x][y];
FOR(i, y, m - 1) h[x][i] = h[x][i + 1];
printf("%lld\n", ans);
FOR(i, x, n - 1) l[i] = l[i + 1];l[n] = ans;
h[x][m]=l[x];
}
}
struct edge_node {
int l, r, size, gs;
ll su;
};
struct seg_tree {
edge_node e[maxn *16];
void pushup(int rt) {
e[rt].su = e[ls].su + e[rs].su;
e[rt].gs = e[ls].gs + e[rs].gs;
}
void build(int l, int r, int rt) {
e[rt].l = l, e[rt].r = r, e[rt].size = r - l + 1;
if (l == r) {
b[l] ? e[rt].gs = 1, e[rt].su = b[l] : e[rt].gs = e[rt].su = 0;
return;
}
int mid = (l + r) >> 1;
build(l, mid, ls);
build(mid + 1, r, rs);
pushup(rt);
}
void delet(int L, int rt) {
if (e[rt].l == e[rt].r) {
e[rt].gs = e[rt].su = 0;
return;
}
if (L <= e[ls].gs) delet(L, ls);
else delet(L - e[ls].gs, rs);
pushup(rt);
}
void add(int L, ll k, int rt) {
if (e[rt].l == e[rt].r) {
e[rt].gs = 1, e[rt].su = k;
return;
}
int mid = (e[rt].l + e[rt].r) >> 1;
if (L <= mid) add(L, k, ls);
else add(L, k, rs);
pushup(rt);
}
ll query(int L, int rt) {
if (e[rt].l == e[rt].r)
return e[rt].su;
if (L <= e[ls].gs) return query(L, ls);
else return query(L - e[ls].gs, rs);
}
} tree;
void part_3() {
FOR(i, 1, m) b[i] = i;
tree.build(1, m*4, 1);
int cnt = m;
FOR(i, 1, q) {
int x = read(), y = read();
int ans = tree.query(y, 1);
printf("%d\n", ans);
tree.delet(y, 1);
tree.add(++cnt, ans, 1);
}
}
queue<ll> qq;
void part_4()
{
FOR(i,1,n) qq.push(calc(i,m));
FOR(i,1,m) b[i] = i;
tree.build(1, m*4, 1);
int cnt = m;
FOR(i, 1, q) {
int x = read(), y = read();
ll ans = tree.query(y, 1);
printf("%lld\n", ans);
tree.delet(y, 1);
qq.pop();
tree.add(++cnt, qq.front(), 1);
qq.push(ans);
}
}
int main() {
// freopen("a.out","w",stdout);
n = read(), m = read(), q = read();
// part 1
if(n<=1000&&m<=1000) {
part_1();
return 0;
}
// part 2
if (q <= 500) {
part_2();
return 0;
}
// part 3
if (n == 1) {
part_3();
return 0;
}
part_4();
return 0;
}