hdu 4533

思路就是把被子拆成4个点,如果某个点(x,y)在(0,0)-(t,t)内的话,如果这个点是左下角或者右上角 面积就+=(t-x)*(t-y),反之面积-=(t-x)*(t-y);(画个图就知道了)
而(t-x)*(t-y) = t*t-(x+y)*t+x*y
所以,需要维护3个系数1,-(x+y),x*y;
在代码中体现

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <climits>
#include <ctime>
#include <numeric>
#include <vector>
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <complex>
#include <deque>
#include <functional>
#include <list>
#include <map>
#include <string>
#include <sstream>
#include <set>
#include <stack>
#include <queue>
using namespace std;
template<class T> inline T sqr(T x) { return x * x; }
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<PII, int> PIII;
typedef pair<LL, LL> PLL;
typedef pair<LL, int> PLI;
typedef pair<LD, LD> PDD;
#define MP make_pair
#define PB push_back
#define sz(x) ((int)(x).size())
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define istr stringstream
#define FOR(i,n) for(int i=0;i<(n);++i)
const double EPS = 1e-6;
const int INF = 0x3fffffff;
const LL LINF = INF * 1ll * INF;
const double PI = acos(-1.0);

using namespace std;

int t;
int n;
struct point{
	LL x,y;
	bool operator<(const point& p) const{
		return max(x,y)<max(p.x,p.y);
	}
	LL getT(){
		return max(x,y);
	}
} p_a[40001],p_b[40001];//p_a表示左下角或者右上角的点,p_b表示左上角或右下角的点

inline bool isDigit(char c){
	return c<='9'&&c>='0';
}

LL& getVal(LL & num){
	num = 0ll;
	char c = getchar();
	while(!isDigit(c)) c = getchar();
	while(isDigit(c)){
		num = num*10+c-'0';
		c = getchar();
	}
	return num;
}

inline point getP(int x,int y){
	point p;
	p.x = x;
	p.y = y;
	return p;
}

int main(void){
      //freopen("","r",stdin);
	  scanf("%d",&t);
	  while(t--){
		  scanf("%d",&n);
		  LL x1,y1,x2,y2;
		  int a_cnt = 0,b_cnt = 0;
		  for(int i = 0;i<n;i++){
	     	  getVal(x1);
		      getVal(y1);
    		  getVal(x2);
	    	  getVal(y2);
			  p_a[a_cnt++] = getP(x1,y1);
			  p_a[a_cnt++] = getP(x2,y2);
			  p_b[b_cnt++] = getP(x2,y1);
			  p_b[b_cnt++] = getP(x1,y2);
		  }
		  sort(p_a,p_a+a_cnt);
		  sort(p_b,p_b+b_cnt);
		  //t:t*t-(x1+x2)*t+x1*x2
		  int q;
		  scanf("%d",&q);
		  int a_i = 0,b_i = 0;
		  LL a1 = 0,b1 = 0,c1 = 0,a2 = 0,b2 = 0,c2 = 0;
		  while(q--){
			  LL tt;
			  getVal(tt);
			  while(true){
				  if(a_i<2*n&&p_a[a_i].getT()<=tt){
					  a1++;
					  b1+=p_a[a_i].x+p_a[a_i].y;
					  c1+=p_a[a_i].x*p_a[a_i].y;
					  a_i++;
				  }else break;
			  }
			  while(true){
				  if(b_i<2*n&&p_b[b_i].getT()<=tt){
					  a2++;
					  b2+=p_b[b_i].x+p_b[b_i].y;
					  c2+=p_b[b_i].x*p_b[b_i].y;
					  b_i++;
				  }else break;
			  }
			  printf("%I64d\n",tt*tt*(a1-a2)-tt*(b1-b2)+(c1-c2));
		  }
	  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值