列表

详情


NC229892. 牛牛玩 generals

描述

n 头牛在一个 的地图上玩 generals。一开始,第 i 头牛的家在第 a_i 个格子上,没有两头牛的家在同一个位置(初始时所有人的兵力为0)。

在接下来的 t 个回合中,可能会发生以下事件:

1. 牛 x 获得了一些增援兵力,并且他使用这些增援占据了 这片地区,这片地区不一定和牛 x 原有地盘相连的(也就是说每个人的地盘可能是多段区间),且最后 每块地区都剩下了 p 的兵力驻守(保证 p 大于等于这片地区任一已被自己占据的地盘上的兵力)

这时牛妹想知道牛x获得了多少增援。

对于,我们设t_ii这个格子上的兵力。

那么若i这个格子原本属于牛x,那么令,否则

那么增援的数量=

注意:如果在一轮占领后,牛y的家被牛x占领了,那么他剩下的所有的地盘和兵力都会归牛x所有

2. 观战的牛妹想要知道牛 x 有多少兵力。

牛妹还想知道,最后还有那些牛的家还没有被占领。

注意:数据保证,当一头牛的家被占领后,接下来就不会有关于这头牛的操作1和操作2。

输入描述

第一行三个正整数,n,m,t

第二行 n 个整数 a_i,表示第i头牛家的位置。

然后 t 行,每行先输入一个整数 op

1. 若 ,再四个整数 x,l,r,p,表示一次占领事件。(

2. 若 ,再输入一个数 x。含义如上。

对于  的数据,

输出描述

对于每一个询问,输出一行一个数表示答案。

最后输出若干行,每行一个数,从小到大输出家没有被别人占领的牛的编号。


示例1

输入:

2 10 3
2 8
1 1 3 6 0
1 2 5 7 1
1 1 4 8 0

输出:

0
3
3
1

说明:

我们用Ⅰ表示牛1,用Ⅱ表示牛2。


上图为每一个操作结束以后的兵力分布。

第一次操作,牛Ⅰ扫荡3~6,这些位置是空地,故牛Ⅰ需要增援0。

第二次操作,牛Ⅱ扫荡5~7,这些位置中牛Ⅰ的有2*0兵力,故牛Ⅱ需要增援2*0+3*1=3,同时这三个位置都成为牛Ⅱ的1兵力。

第三次操作,牛Ⅰ扫荡4~8,这些位置中牛Ⅱ的有3*1+1*0兵力,故牛Ⅰ需要增援3+5*0=3,同时这五个位置都成为牛Ⅰ的0兵力,牛Ⅱ被牛Ⅰ吃掉。

最后只有牛Ⅰ活了下来 。


原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 193ms, 内存消耗: 9048K, 提交时间: 2021-12-11 12:35:13

#include<bits/stdc++.h>
using namespace std;
int mk[100010];
struct tup{
	int l,r,w,p;
	bool operator<(tup x)const{
		return l<x.l;
	}
};
set<tup>st;
set<tup>::iterator it;
int ans[100010],a[100010],fa[100010],sk[100010];
int find(int x){
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main(){
	int n,m,t;
	scanf("%d%d%d",&n,&m,&t);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		mk[a[i]]=i;fa[i]=i;
	}
	for(int i=1;i<=m;++i)st.insert((tup){i,i,0,mk[i]});
	while(t--){
		int f;
		scanf("%d",&f);
		if(f==1){
			int x,l,r,p,cnt=0;
			scanf("%d%d%d%d",&x,&l,&r,&p);
			it=st.upper_bound((tup){r,0,0,0});
			int ans1=(r-l+1)*p,ans2=0,ans3=0;
			--it;
			while(1){
				int l1=it->l,r1=it->r,w1=it->w,p1=it->p;
				if(r1<l)break;
				--it;
				st.erase((tup){l1,r1,w1,p1});
				p1=find(p1);
				int l2=max(l1,l),r2=min(r1,r);
				if(p1==x)ans2+=w1*(r2-l2+1);
				else{
					ans3+=w1*(r2-l2+1);
					ans[p1]-=w1*(r2-l2+1);
					if(l2<=a[p1]&&r2>=a[p1])sk[++cnt]=p1;
				}
				if(l1<l)st.insert((tup){l1,l-1,w1,p1});
				if(r1>r)st.insert((tup){r+1,r1,w1,p1});
			}
			st.insert((tup){l,r,p,x});
			ans[x]+=ans1-ans2;
			printf("%d\n",ans1-ans2+ans3);
			for(int i=1;i<=cnt;++i)fa[sk[i]]=x,ans[x]+=ans[sk[i]];
		}
		else{
			int x;
			scanf("%d",&x);
			printf("%d\n",ans[x]);
		}
	}
	for(int i=1;i<=n;++i)if(fa[i]==i)printf("%d\n",i);
}

上一题