BZOJ2738【整体二分】【树状数组】

/* I will wait for you */

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<vector>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#define make make_pair
#define fi first
#define se second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int maxn=1010;
const int maxm=500010;
const int maxs=26;
const int INF=1<<29;
const int P=1000000007;
const double error=1e-9;

struct ask{ int t,x1,y1,x2,y2,c,pos,cur; }e[maxm],e1[maxm],e2[maxm];

int n,q,cnt,mx,s[maxn][maxn],ans[maxm],tmp[maxm];

inline int read()  
{  
    int x=0,f=1;char c=getchar();  
    while(c>'9'||c<'0') f=(c=='-'?-1:1),c=getchar();  
    while(c<='9'&&c>='0') (x*=10)+=c-'0',c=getchar();  
    return x*f;  
} 

inline void ins(int x,int y,int c)
{
	for(int i=x;i<=n;i+=i&-i) for(int j=y;j<=n;j+=j&-j) s[i][j]+=c;
}

inline int sum(int x,int y)
{
	int f=0;for(int i=x;i;i-=i&-i) for(int j=y;j;j-=j&-j) f+=s[i][j];return f;
}

inline int query(int x1,int y1,int x2,int y2)
{
	return sum(x1-1,y1-1)+sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1);
}

inline void work(int l,int r,int a,int b)
{	
	if(l==r) 
	{
		for(int i=a;i<=b;i++) if(e[i].t) ans[e[i].pos]=l;
	}
	else
	{
		int mid=(l+r)>>1;
		
		for(int i=a;i<=b;i++) if(!e[i].t&&e[i].c<=mid) ins(e[i].x1,e[i].y1,1);
		
		for(int i=a;i<=b;i++) if(e[i].t)
			tmp[i]=query(e[i].x1,e[i].y1,e[i].x2,e[i].y2);
		
		for(int i=a;i<=b;i++) if(!e[i].t&&e[i].c<=mid) ins(e[i].x1,e[i].y1,-1);
	
		int q1=0,q2=0;
		for(int i=a;i<=b;i++)
		{
			if(!e[i].t) e[i].c<=mid?e1[q1++]=e[i]:e2[q2++]=e[i];
			if(e[i].t) (tmp[i]+e[i].cur>=e[i].c)?e1[q1++]=e[i]:(e[i].cur+=tmp[i],e2[q2++]=e[i]);
		}
		
		for(int i=0;i<q1;i++) e[a+i]=e1[i];
		for(int i=0;i<q2;i++) e[a+q1+i]=e2[i];
		
		work(l,mid,a,a+q1-1);
		if(mid+1<=r&&a+q1<=b) work(mid+1,r,a+q1,b);
	}
}

int main()
{
	n=read(),q=read();
	
	for(int i=1,c;i<=n;i++) for(int j=1;j<=n;j++)
		c=read(),e[++cnt]=(ask){0,i,j,0,0,c,cnt},mx=max(mx,c);
		
	for(int i=1;i<=q;i++)
	{
		int x1=read(),y1=read(),x2=read(),y2=read(),k=read();
		e[++cnt]=(ask){1,x1,y1,x2,y2,k,cnt};
	}

	memset(ans,-1,sizeof(ans)),work(0,mx,1,cnt);
	for(int i=1;i<=cnt;i++) if(ans[i]!=-1) printf("%d\n",ans[i]);
	return 0;
}

你可能感兴趣的:(BZOJ2738【整体二分】【树状数组】)