UvaLive 3525:Wild West

Portal:https://vjudge.net/problem/UVALive-3525

解析:

我们假设求所求元素的补集,即满足“存在一个三元组\((x_i,y_i,z_i)\),使得\(x_i\geq x,y_i\geq y,z_i\geq z\)的三元组个数,我们先把所有元素按\(z\)降序排序,每次添加相同\(z\)的点到二维平面上,这等价于维护一个单调递减的极大子集,用set进行插入与删除即可。

当然写这篇是为了强调几个使用set维护点集的注意事项:

  • 注意加点时别忘了先判它有没有优势
  • 注意指针上的操作
  • 别忘了删点
  • upper_bound是找出第一个与查找元素不同的大于等于它的位置,而不是大于

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm> 
#include <vector> 
#include <set>

#define rep(i,x,y) for (int i=x;i<=y;i++)
#define dep(i,y,x) for (int i=y;i>=x;i--)
#define mp(x,y) make_pair(x,y)
#define sz(x) (int)(x.size())

using namespace std;

typedef long long LL;

const int maxn=100000+21;
const int INF=(1<<30);

struct node{
 int x,y,z;
 bool operator < (node b) {return z<b.z;}
} a[maxn];


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

int n,L,R,last;

LL cur,ans,m;

set<pair<int,int> > S;

bool cmp(node a,node b) {return a.z>b.z;}

void add(int x,int y)
{
 if (S.empty()) {S.insert(mp(x,y));cur+=x*y;return;}
 
 set<pair<int,int> >::iterator it=S.upper_bound(mp(x,y)),prev,succ;
 if ((*it).second>=y) return;
 
 if ((it==S.end())||((*it).first>x)) it--;

 succ=it,succ++;
 if (succ!=S.end())
 {
  cur-=(LL)((*succ).first-(*it).first)*(LL)(*succ).second;
  cur+=(LL)((*succ).first-x)*(LL)((*succ).second);
 }

 while (((*it).second)<=y)
 {
  prev=it,prev--;
  cur-=(LL)((*it).second)*(LL)((*it).first-(*prev).first);
  if (it==S.begin()) {S.erase(it);break;} else {S.erase(it);it=prev;}
 }

 cur+=(LL)(y)*(LL)(x-(*it).first);
 S.insert(mp(x,y));
}

int main()
{
 while ((scanf("%d%lld",&n,&m)==2) && n && m)
 {
  rep(i,1,n) a[i].x=read(),a[i].y=read(),a[i].z=read();
  sort(a+1,a+n+1,cmp);
  
  S.clear(); S.insert(mp(0,INF));
  ans=cur=last=0,a[0].z=a[1].z;
  
  while (last<n)
  {
   L=R=last+1;
   while (a[R+1].z==a[L].z) R++;
   
   ans+=(LL)(a[last].z-a[L].z)*cur;
   rep(i,L,R) add(a[i].x,a[i].y);

   last=R;
  }
  
  ans+=(LL)(a[last].z)*cur;

  printf("%lld\n",m*m*m-ans);
 }
 
 return 0;
}

怒艹rank1,开心

posted @ 2017-02-14 23:41  Krew  阅读(229)  评论(0)    收藏  举报