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,开心

浙公网安备 33010602011771号