noip 2017 列队 (45行!!!!)

题目的话,我扔 https://www.luogu.org/problemnew/show/P3960

这题在仔细思考(看题解)后感觉还是挺简单的。

因为对于每一次操作只会影响当前行和最后一列,那么我们可以用动态开点线段树来维护每一行的前m - 1 个然后在用一个维护最后一列,那么就可以很愉快的A了。

代码(45行有木有!!!!)

#include<bits/stdc++.h>
#define ll long long
#define N 4600005
using namespace std;
int ch[N][2], root[N], del[N], tot, n, m, q, M;
vector<ll> extral[N]; 
int find(int l, int r, int rt, int x){ // 找当前位置
	if(l == r) return l;
	int mid = (l + r) >> 1, ret = mid - l + 1 - del[ch[rt][0]];
	if(ret >= x) return find(l, mid, ch[rt][0], x);
	else return find(mid + 1, r, ch[rt][1], x - ret);
}
void dele(int l, int r, int &rt, int x){ // 删掉当前点
	if(!rt) rt = ++ tot;
	del[rt] ++;
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(x <= mid) dele(l, mid, ch[rt][0], x);
	else dele(mid + 1, r, ch[rt][1], x);
}
ll DL(int x, ll val){ // 删掉最后一行的某一个点并把val 加进去
	int pos = find(1, M, root[n + 1], x); ll ans;
	dele(1, M, root[n + 1], pos);
	if(pos <= n) ans = (ll)pos * m; else ans = extral[n + 1][pos - n - 1];
	extral[n + 1].push_back(val?val:ans);
	return  ans;
}
ll query(int x, int y){ // 处理非最后一行的情况
	int pos = find(1, M, root[x], y); ll ans;
	dele(1, M, root[x], pos);
	if(pos < m) ans = (ll)(x - 1) * m + pos; else ans = extral[x][pos - m];
	extral[x].push_back(DL(x, ans));
	return ans;
}
int main(){
	scanf("%d%d%d", &n, &m, &q);
	M = max(n, m) + q;
	for(;q --;){
		int x, y;
		scanf("%d%d", &x, &y);
		if(y != m) printf("%lld\n", query(x, y));
		else printf("%lld\n", DL(x, 0)); 
	}
	return 0;
}//呵呵呵呵呵呵呵呵呵呵呵

注意一下数组要开大一些(log),不然会凉凉。

嘿嘿嘿嘿嘿嘿嘿嘿。

哈哈哈哈哈哈哈哈嗝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值