【poj 3067 cdoj 383】Japan 树状数组

来源:互联网 发布:人口密度数据 编辑:程序博客网 时间:2024/06/01 21:49

题意:

日本有N个城市在东边,从北至南编号为1 2 3,,,N,M个城市在西边,从北至南编号为1 2 ,,,,M,K条高速公路将被建造

高速公路的一端在西边,一端在东边

输入有多组样例,

每组样例第一行为

n m k

接下来有k行,分别为高速公路的端点

求高速公路的交点有多少个,不包括以城市为相交点

终于放假啦,啦啦啦

画图容易观察得出,将左边从小到大排序一次以后,再逐步插入右边的点,当右边存在一个点的编号比他大的时候,总和就会增加一。所以用树状数组来维护。

但是,需要注意了,可能从一个点出发存在多个点,所以要先处理完所有由同一个左顶点出发的点,并记录下来,然后当需要更新下一个点的时候,再更新树状数组中维护的前缀和,而在这里有很多的细节需要注意,so 在改的时候一定要注意考虑到所有的情况,细心一点,包括 cnt 变量,和栈维护的更新信息的位置这些地方错了将会是非常可惜的,一定要细心细心再细心,考虑周全

对了,还有一点很坑,没搞懂为什么非要用long long来存

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<stack>#define maxn 500020#define ll long longusing namespace std;ll T,n,m,k,ans;stack<ll>s;struct node{ll l,r;node():l(0),r(0){}bool operator <(const node& x)const{return l<x.l;}}nod[maxn];ll c[maxn*4];ll lowbit(ll x){return x&(-x);}void updata(ll x,ll add){while(x<=m){c[x]+=add;x+=lowbit(x);}}ll sum(ll x){ll ans=0;while(x){ans+=c[x];x-=lowbit(x);}return ans;}void solve(){ll cnt=0;for(ll i=1;i<=k;i++){if(nod[i].l!=nod[i-1].l){cnt=i-1;while(!s.empty() ){ll x=s.top() ;updata(x,1);s.pop() ;}}if(nod[i].l==nod[i-1].l||nod[i].l==nod[i+1].l){ll y=nod[i].r; s.push(y);ans+=cnt-sum(y);continue;}cnt=i;ll y=nod[i].r;updata(y,1);ans+=cnt-sum(y);}}int main(){scanf("%lld",&T);for(ll p=1;p<=T;p++){while(!s.empty() )s.pop();memset(c,0,sizeof(c));ans=0;scanf("%lld%lld%lld",&n,&m,&k);ll a,b;for(ll i=1;i<=k;i++){scanf("%lld%lld",&a,&b);nod[i].l=a;nod[i].r=b;}sort(nod+1,nod+k+1);solve();printf("Test case %lld: %lld\n",p,ans);}return 0;} 


0 0