【bzoj2441】 中山市选2011小W的问题 线段树

来源:互联网 发布:网站数据库是干嘛的 编辑:程序博客网 时间:2024/05/01 13:33

果然考试时候写题乱脑子,代码写的又臭又长。

首先五个点其实是找三个点V字形的,然后f[i]表示以i为结尾的V的个数,其实就是所有i左边纵坐标比i小的数中前面纵坐标比i大的数的个数,说起来好麻烦,意会即可。

第一眼感觉是树套树可做。

后来想了想,弃疗了。

先不考虑相等的情况。

果断想一想离线算法,按照纵坐标排序,从小到大插入数列中,每个点i维护一个data[i]表示未插入序列中横坐标小于i的数的个数,那么f[j]就等于1到j-1中所有已插入的data之和,为什么呢?因为现在在未插入数列中的数都是大于j的纵坐标的。然后每次插入j,就把j+1到n的所有data全部-1,注意赋初始值的时候的处理。

考虑上相等的情况果断炸了。

横坐标可以相等,纵坐标可以相等。

代码真心没法看。


#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>#define maxn 100010#define mod 1000000007using namespace std;struct yts{int l,r,data,tag,len;}t[4*maxn];struct yts1{int x,y,id,x1;}p[maxn];int n;int f[maxn][2];bool cmp(yts1 x,yts1 y){return x.x<y.x;}bool cmpp(yts1 x,yts1 y){return x.x>y.x;}bool cmp1(yts1 x,yts1 y){return x.id<y.id;}bool cmp2(yts1 x,yts1 y){return x.id>y.id;}bool cmp3(yts1 x,yts1 y){return x.y<y.y;}void update(int i){if (t[i].l==t[i].r) return;t[i].len=t[i*2].len+t[i*2+1].len;t[i].data=0;if (t[i*2].len) t[i].data=(t[i].data+t[i*2].data)%mod;if (t[i*2+1].len) t[i].data=(t[i].data+t[i*2+1].data)%mod;}void push(int i,int x){t[i].data=(t[i].data+t[i].len*x)%mod;t[i].tag=(t[i].tag+x)%mod;}void release(int i){if (t[i].l==t[i].r) return;if (!t[i].tag) return;push(i*2,t[i].tag);push(i*2+1,t[i].tag);t[i].tag=0;}void build(int i,int l,int r){t[i].l=l;t[i].r=r;t[i].tag=0;t[i].data=0;t[i].len=0;if (l==r) return;int mid=(l+r)/2;build(i*2,l,mid);build(i*2+1,mid+1,r);}void modify1(int i,int x,int d){if (t[i].l==t[i].r) {t[i].len=1;t[i].data=(t[i].tag+d)%mod;return;}release(i);int mid=(t[i].l+t[i].r)/2;if (x<=mid) modify1(i*2,x,d);else modify1(i*2+1,x,d);update(i);}void modify2(int i,int l,int r,int x){if (l>r) return;if (l<=t[i].l && t[i].r<=r) {push(i,x);return;}release(i);int mid=(t[i].l+t[i].r)/2;if (l<=mid) modify2(i*2,l,r,x);if (mid<r) modify2(i*2+1,l,r,x);update(i);}int query(int i,int l,int r){if (!t[i].len) return 0;if (l<=t[i].l && t[i].r<=r) return t[i].data;release(i);int mid=(t[i].l+t[i].r)/2;int ans=0;if (l<=mid) ans+=query(i*2,l,r);if (mid<r) ans+=query(i*2+1,l,r);return ans;}void solve0(){sort(p+1,p+n+1,cmp3);build(1,1,n);for (int i=1;i<=n;i++){int j=i;while (j<n && p[j+1].y==p[i].y) j++;for (int k=i;k<=j;k++) modify2(1,p[k].x1,n,-1);for (int k=i;k<=j;k++) f[p[k].id][0]=query(1,1,p[k].x-1);for (int k=i;k<=j;k++) modify1(1,p[k].id,p[k].x-1);i=j;}}void solve1(){sort(p+1,p+n+1,cmp3);build(1,1,n);for (int i=1;i<=n;i++){int j=i;while (j<n && p[j+1].y==p[i].y) j++;for (int k=i;k<=j;k++) modify2(1,1,p[k].x-1,-1);for (int k=i;k<=j;k++) f[p[k].id][1]=query(1,p[k].x1,n);for (int k=i;k<=j;k++) modify1(1,p[k].id,n-p[k].x1+1);i=j;}}int main(){//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y);sort(p+1,p+n+1,cmp);int mx=1;p[1].x1=1;for (int i=2;i<=n;i++){if (p[i].x!=p[i-1].x) mx=i;p[i].x1=mx;}for (int i=1;i<=n;i++) p[i].x=p[i].x1;p[n].x1=n+1;for (int i=n-1;i>=1;i--){if (p[i].x!=p[i+1].x) p[i].x1=p[i+1].x;else p[i].x1=p[i+1].x1;}for (int i=1;i<=n;i++) p[i].id=i;solve0();solve1();long long ans=0;for (int i=1;i<=n;i++)  ans=(ans+(long long)f[i][0]*f[i][1]%mod)%mod;printf("%lld\n",ans);return 0;}


0 0