[Treap 笛卡尔树 扫描线 补集转化] BZOJ 2658 [Zjoi2012]小蓝的好友(mrx)

来源:互联网 发布:linux 查看磁盘空间 编辑:程序博客网 时间:2024/06/04 08:24

这个先转化成全部矩形 C2R+1C2C+1 减去不包含点的矩形
我们考虑扫描线 也就是以当前直线作为右边界的矩形有多少个
对于每个纵坐标 设h表示最左能扩展到哪里
假设hmin(1,n)=hx
那么答案至少应该C2C+1hmin
然后还要加上C2x1(hmin(1,x1)hx)C2Cx(hmin(x+1,C)hx)
然后还要继续递归式的加 这个可以用笛卡尔树维护
扫描线向右移就h都+1 碰到点就h降为0

#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef pair<int,int> abcd;typedef long long ll;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005;int n,R,C; abcd a[N];ll Ans;inline ll calc(int n){ return (ll)n*(n+1)/2; }struct node{  node *l,*r; int size;  int add,h; ll ans;  void upd(){    size=1,ans=0;    if (l) size+=l->size,ans+=l->ans+(ll)(l->h-h)*calc(l->size);    if (r) size+=r->size,ans+=r->ans+(ll)(r->h-h)*calc(r->size);  }  void mark(int t){ add+=t,h+=t; }  void push(){ if(l)l->mark(add); if(r)r->mark(add); add=0; }}nodes[N],*root;typedef pair<node*,node*> Droot;inline int ran(){  static int x=31253125; x+=(x<<4)+1; return x&65536;}inline node* M(node *x,node *y){  if (!x || !y) return x?x:y;  x->push(); y->push();  if (x->h>y->h || (x->h==y->h && ran()))    return y->l=M(x,y->l),y->upd(),y;  else    return x->r=M(x->r,y),x->upd(),x;}inline int Size(node *x){ return x?x->size:0; }inline Droot S(node *x,int k){  if(!x) return Droot(NULL,NULL);  x->push(); Droot y;  if (Size(x->l)>=k){    y=S(x->l,k);    x->l=y.second; x->upd();    y.second=x;  }else{    y=S(x->r,k-Size(x->l)-1);    x->r=y.first; x->upd();    y.first=x;  }  return y;}int main(){  freopen("mrx.in","r",stdin);  freopen("mrx.out","w",stdout);  read(R); read(C); read(n);  for (int i=1;i<=n;i++) read(a[i].first),read(a[i].second);  sort(a+1,a+n+1);   Ans=calc(R)*calc(C);  for (int i=1;i<=C;i++) nodes[i].size=1,root=M(root,nodes+i);  int pnt=1;  for (int i=1;i<=R;i++){    root->mark(1);    while (pnt<=n && a[pnt].first==i){      Droot t1=S(root,a[pnt].second-1),t2=S(t1.second,1);      t2.first->h=0;      root=M(M(t1.first,t2.first),t2.second);      pnt++;    }    Ans-=root->ans+(ll)root->h*calc(root->size);  }  printf("%lld\n",Ans);  return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机程序出现异常怎么办 公众号企业名称是*怎么办 家人生命受到威胁怎么办 海淘看不懂英文怎么办 对英语不感兴趣怎么办 装修无合同起诉怎么办 上海离职后档案怎么办 公司注销了银行帐户怎么办 360借条注销了怎么办 注销营业执照公章丢失怎么办 工厂招聘信息有假怎么办 个体餐饮怎么办核名 见父母后接下来怎么办 工商核名重名怎么办 核名通知书过期怎么办 包头鼎太风华怎么办 用人单位不续签劳动合同怎么办 全是英文看不懂怎么办 孩子智力发育晚怎么办 公司比赛成绩不好怎么办 解压手续过期了怎么办 违章通知单丢了怎么办 住在朋友家怎么办暂住证 告知单丢了怎么办 身份证丢了怎么办暂住证 合肥居住证失效了怎么办 异地办牌照暂住证怎么办 外地牌照上保险怎么办 住公租房怎么办暂住证 暂住证怎么办 异地学车 外地人怎么办北京市工作居住证 电大挂科很多怎么办 南通电大挂科怎么办 大学出现挂科怎么办 在北京没暂住证怎么办 我想买北京车牌怎么办 想买北京车牌怎么办 北仑这边暂住证怎么办 深圳居住证过期了怎么办 北京不办暂住证怎么办 上海居住证怎么办办理入学