codechef Killing Monsters

Topic: The chef is playing a small game of fighting monsters. At the beginning of the game, there are n monsters lined up in a row, numbered 0 ∼ n − 1 from left to right. The initial HP of the i-th monster is hi. When the monster's HP is less than or equal to 0, the monster will die. The chef has to perform q operations. In each operation, the chef will choose two integers x and y, and shoot at the monster whose index k satisfies k&x = k (here & stands for bitwise AND operation). Monsters hit by cannonballs drop y blood. Please tell Chef how many monsters are still alive after each operation he does.

What to do: Consider chunking operations

Preprocess the blood volume to be deducted with the subscript i in each block. 
Then for a certain subscript i, violence starts from the first block, runs to the first block with insufficient health, and then runs violently in that block. 
See which seat it reaches and just run out of HP, and then the x seat ans[x]–. (ans is a differential array, which means that there is one less monster from x to the end) 
and finally the answer can be accumulated and output. 

Code:

#include<bits/stdc++.h>
#define N 300005
#define M 605
#define int long long
using namespace std;
int n,m,num,block,limit,len;
int a[N],x[N],y[N],f[M][N],l[N],r[N],ans[N];
inline int gt(int x){return (x-1)/block+1;}
signed main(){
	scanf("%lld",&n);limit=1;
	for (;limit<n;limit<<=1) len++;limit--;
	for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
	scanf("%lld",&m);block=(int)sqrt(m);
	num=m/block;if (m%block) num++;
	for (int i=1;i<=num;i++) l[i]=(i-1)*block+1,r[i]=i*block;
	for (int i=1;i<=m;i++){
		scanf("%lld%lld",&x[i],&y[i]);
		x[i]&=limit;f[gt(i)][x[i]]+=y[i];
	}
	for (int i=1;i<=num;i++)
		for (int k=0;k<len;k++)
			for (int j=0;j<=limit;j++)
				if (j>>k&1) f[i][j^(1<<k)]+=f[i][j];//Enumerate j, obviously (j^(1<<k))&j= =j, then the blood deducted by j (j^(1<<k)) will definitely be deducted (equivalent to the subscript k in the enumeration title)
	years[1]=n;
	for (int i=1;i<=n;i++){
		int j=1;
		for (;j<=num&&a[i]>f[j][i-1];j++) a[i]-=f[j][i-1];
		if (j>num) continue;
		for (j=l[j];j<=m;j++) if ((x[j]&(i-1))==i-1){
			if (a[i]>y[j]) a[i]-=y[j];
			else break;
		}
		years[j]--;
	}
	for (int i=1;i<=m;i++)
		ans[i]+=ans[i-1],printf("%lld\n",ans[i]);
	return 0;
}

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325590647&siteId=291194637