这几天对着notonlysuccess的完全版线段树,因为登不了国外的OJ,所以只跟着刷了POJ和HDOJ,之后有好的线段树题目会陆续更新上来!
简单介绍下我的代码风格:
一:maxn题目所给区间,节点数maxn<<2.
二:lson,rson表示左儿子和右儿子
我喜欢宏定义#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
得注意下如果节点存的不是点而是线段的时候,得#define rson id<<1|1,mid,r
三:update函数:更新操作
四:PushDown函数,懒惰标记下传给儿子,在成端更新的时候为了效率我们只更新到指定段,并不更新到
叶子节点,而当下一次操作询问到该段的某一部分,或者是对该段的某一部分进行更新操作的时候,
就需要将之前的懒惰标记向下传递
五:PushUp函数,当执行完更新操作后,将儿子节点的信息更新到父节点,这样父节点的权值一直是正确
的,询问指定区间的时候,只要返回该区间对应的权值
线段树的题型主要分为四类:单点更新 成段更新 区间合并 扫描线
一:单点更新
题意:单点更改,询问区间和
思路:只需要update函数单点更改,PushUp函数维护区间和
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 50080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int A[maxn];
char ope[10];
struct ST
{
int l,r,key;
}st[maxn<<2];
void PushUp(int id)
{
st[id].key = st[id<<1].key + st[id<<1|1].key;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r;
if(l == r)
{
st[id].key = A[l];
return;
}
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
PushUp(id);
}
void update(int id,int pos,int add)
{
if(st[id].l == pos && st[id].r == pos)
{
st[id].key += add;
return;
}
if(st[id<<1].r >= pos)
update(id<<1,pos,add);
else update(id<<1|1,pos,add);
PushUp(id);
}
int query(int id,int l,int r)
{
if(st[id].l == l && st[id].r == r) return st[id].key;
if(st[id<<1].r >= r) return query(id<<1,l,r);
if(st[id<<1|1].l <= l) return query(id<<1|1,l,r);
return query(id<<1,l,st[id<<1].r) + query(id<<1|1,st[id<<1|1].l,r);
}
int main()
{
//freopen("in.txt","r",stdin);
int t; scanf("%d",&t);
for(int cas = 1;cas <= t;cas++)
{
int n; scanf("%d",&n);
for(int i = 1;i <= n;i++) scanf("%d",&A[i]);
buildtree(1,1,n);
printf("Case %d:\n",cas);
while(scanf("%s",ope)!=EOF && ope[0]!='E')
{
int u,v; scanf("%d%d",&u,&v);
if(ope[0] == 'Q') printf("%d\n",query(1,u,v));
if(ope[0] == 'A') update(1,u,v);
if(ope[0] == 'S') update(1,u,-v);
}
}
return 0;
}
题意:单点更改,询问区间最大值
思路:update函数单点更改,PushUp函数维护区间最大值
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 200080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int A[maxn];
struct ST
{
int l,r,key;
}st[maxn<<2];
inline int max(int a,int b)
{
return a>b?a:b;
}
void PushUp(int id)
{
st[id].key = max(st[id<<1].key,st[id<<1|1].key);
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r;
if(l == r)
{
st[id].key = A[l];
return;
}
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
PushUp(id);
}
void update(int id,int pos,int newk)
{
if(st[id].l == pos && st[id].r == pos)
{
st[id].key = newk;
return;
}
if(st[id<<1].r >= pos)
update(id<<1,pos,newk);
else update(id<<1|1,pos,newk);
PushUp(id);
}
int query(int id,int l,int r)
{
if(st[id].l == l && st[id].r == r) return st[id].key;
if(st[id<<1].r >= r) return query(id<<1,l,r);
if(st[id<<1|1].l <= l) return query(id<<1|1,l,r);
return max(query(id<<1,l,st[id<<1].r),query(id<<1|1,st[id<<1|1].l,r));
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)==2)
{
for(int i = 1;i <= n;i++) scanf("%d",&A[i]);
char ope[2];int u,v;
buildtree(1,1,n);
for(int i = 1;i <= m;i++)
{
scanf("%s%d%d",ope,&u,&v);
if(ope[0] == 'Q') printf("%d\n",query(1,u,v));
else update(1,u,v);
}
}
return 0;
}
HDU1394 Minimum Inversion Number
题意:给一行数,每次可将第一个移到最后一个,求所有情况中的最小逆序数
思路:节点表示区间[l,r]出现了多少个数.每读入一个数,query一下即可得到该数的逆序对,然后update.求出逆序然后就是简单递推
PS:归并排序求逆序数的方法必须掌握,用线段树的话如果数太大是行不通的,可切下POJ2299就知道
还有这里数是0到n.要么建树buildtree(1,0,n-1),要么将A[i]集体++.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 5080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int A[maxn];
struct ST
{
int l,r,key;
}st[maxn<<2];
inline int min(int a,int b)
{
return a>b?b:a;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].key = 0;
if(l == r) return;
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
}
void PushUp(int id)
{
st[id].key = st[id<<1].key + st[id<<1|1].key;
}
void update(int id,int pos)
{
if(st[id].l == pos && st[id].r == pos)
{
st[id].key = 1;
return;
}
if(st[id<<1].r >= pos)
update(id<<1,pos);
else update(id<<1|1,pos);
PushUp(id);
}
int query(int id,int l,int r)
{
if(st[id].l == l && st[id].r == r) return st[id].key;
if(st[id<<1].r >= r) return query(id<<1,l,r);
if(st[id<<1|1].l <= l) return query(id<<1|1,l,r);
return query(id<<1,l,st[id<<1].r) + query(id<<1|1,st[id<<1|1].l,r);
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF && n)
{
int sum = 0;
buildtree(1,1,n);
for(int i = 1;i <= n;i++)
{
scanf("%d",&A[i]); A[i]++;
update(1,A[i]);
if(A[i] < n) sum += query(1,A[i]+1,n);
}
//sum就是初始逆序数
int now = sum,ans = sum;
for(int i = 1;i < n;i++)
{
if(A[i] < n) now += 2*query(1,A[i]+1,n) - n + 1;
else now -= n-1;
ans = min(ans,now);
}
printf("%d\n",ans);
}
return 0;
}
题意:往黑板贴海报,1.尽量往上2.尽量靠左
思路:节点存区间最大值,update函数单点更改后,PushUp函数向上传递维护区间最大值
PS:建树的时候区间上限只需要min(h,n).
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 200080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int w,h,pos;
inline int max(int a,int b)
{
return a>b?a:b;
}
inline int min(int a,int b)
{
return a>b?b:a;
}
struct ST
{
int l,r,key;
}st[maxn<<2];
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].key = w;
if(l == r) return;
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
}
void PushUp(int id)
{
st[id].key = max(st[id<<1].key,st[id<<1|1].key);
}
void update(int id,int len)
{
if(st[id].l == st[id].r)
{
pos = st[id].l;
st[id].key -= len;
return;
}
if(st[id<<1].key >= len)
update(id<<1,len);
else if(st[id<<1|1].key >= len)
update(id<<1|1,len);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d%d%d",&h,&w,&n)==3)
{
buildtree(1,1,min(n,h));
for(int i = 1;i <= n;i++)
{
int a;pos = -1;
scanf("%d",&a);
if(st[1].key >= a)
update(1,a); printf("%d\n",pos);
}
}
return 0;
}
题意:N个人,每个人找个地方插队。求最终队形
思路:挺巧的一道题,先读入操作,然后反向操作,一个人要插在i之后,则他前面必须有i个空位。非空位说明比他晚来的人有人插在他前面嘛。update函数即是占位,PushUp函数维护区间剩余空位数
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 200080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int u[maxn],v[maxn],POS,ans[maxn];
struct ST
{
int l,r,res;
}st[maxn<<2];
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].res = r - l +1;
if(l == r) return;
int mid = (l+r)>>1;
buildtree(lson);
buildtree(rson);
}
void PushUp(int id)
{
st[id].res = st[id<<1].res + st[id<<1|1].res;
}
void update(int id,int pos)
{
if(st[id].l == st[id].r)
{
st[id].res = 0;
POS = st[id].l;
return;
}
if(st[id<<1].res >= pos)
update(id<<1,pos);
else update(id<<1|1,pos-st[id<<1].res);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
buildtree(1,1,n);
for(int i = 1;i <= n;i++)
{
scanf("%d%d",&u[i],&v[i]);
}
for(int i = n;i >= 1;i--)
{
update(1,u[i]+1);
ans[POS] = v[i];
}
for(int i = 1;i <= n;i++)
{
printf("%d",ans[i]);
if(i == n) printf("\n");
else printf(" ");
}
}
return 0;
}
POJ2886 Who Gets the Most Candies?
题意:N个小伙伴围在一起,每个小伙伴手中有张卡片,意味着下一个出来的是他左边或右边第几个,求第K个出来的是谁。K即是N内对应因子数最多的那个。
思路:预处理求N内对应的K,将环看成直线,每一次用取余的方法得到要T的是第几个人,再update.
/*
反素数的求法。
搜百度搜了好久都找不到细讲的,最后既然搜到队长的博客O(∩_∩)O哈哈~
显然素数的因子数为2;
至于非素数,可以分解为质因子之积
i=2^b1*3^b2^5^b3------等等
所以i的因子个数=(b1+1)*(b2+1)*(b3+1)~~~*(bn+1)
反素数的求法:筛选法+DP;素数的约数个数显然是2,对于合数,先求出其
一个质因子,假设是a1,则反复试除a1,求得b1,而在DP过程中已经求得了
N/a1的约数个数,设为g(N/a1),则g(N)=g(N/a1)*(b1+1)/b1
求出反素数后,我们就可以得到n内最大的那个反素数设为k,问题转换为如何求得
谁是第k个跳出来的人。
*/
#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 500108
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
bool isp[maxn+1000];
int num[maxn+1000];
int yinshu[maxn+1000];
int maxid[maxn+1000];//用来存最大反素数的id
char Name[maxn+1000][12];
int nextt[maxn+1000];
int winnerid;
struct ST
{
int l,r,res;
}st[4*maxn];
void init()//筛选素数
{
isp[1]=1;
for(int i=2;i<720;i++)
{
if(!isp[i])
{
for(int j=i*i;j<=maxn;j+=i)
{
isp[j]=1;
if(!yinshu[j])
yinshu[j]=i;
}
}
}
}
void get()//这一步是求出maxn内,每个数因子数的个数
{
num[0]=0;
num[1]=1;
maxid[1]=1;
for(int i=2;i<=maxn;i++)
{
if(!isp[i])num[i]=2;//如果是个素数,那么他的因子数就是2
else//如果不是个素数,那么
{
int s,t,ant=1;
s=t=i/yinshu[i];//接下来我们要反复除yinshu[i].求出i的质因子yinshu[i]的指数
while(t==yinshu[i]||(isp[t]&&yinshu[i]==yinshu[t]))
{
t/=yinshu[i];
ant++;
}
num[i]=num[s]*(ant+1)/ant;
}
if(num[i]>num[maxid[i-1]])
{
maxid[i]=i;
}
else maxid[i]=maxid[i-1];
}
}
void buildtree(int id,int l,int r)
{
st[id].l=l;st[id].r=r;
st[id].res=r-l+1;
if(l==r)return;
int mid=(l+r)>>1;
buildtree(lson);
buildtree(rson);
}
int update(int id,int l,int r,int p)//要来T第P个人
{
st[id].res--;
if(st[id].l==st[id].r)
{
return st[id].l;
}
if(st[id<<1].res>=p)
{
return update(id<<1,l,st[id<<1].r,p);
}
else return update(id<<1|1,st[id<<1|1].l,r,p-st[id<<1].res);
}
int main()
{
int n,star,sum,p;//sum用来存此时的真实人数
init();get();
while(scanf("%d%d",&n,&star)==2)
{
sum=n;
buildtree(1,1,n);
for(int i=1;i<=n;i++)
{
scanf("%s%d",Name[i],&nextt[i]);
}
p=star;
//想想如何得到要踢的人是第几个人
for(int i=1;i<=n;i++)
{
int z=update(1,1,n,p);
if(i==maxid[n])
{
winnerid=z;
}
sum--;
if(nextt[z]>0)//要踢左边第几个
{
if(sum<=1)p=1;
else
{ p=p-1+(nextt[z]%sum);
if(p>sum)p-=sum;
if(p<=0)p+=sum;
}
}
else//要踢右边第几个
{
if(sum<=1)p=1;
else
{
p=p+(nextt[z]%sum);
if(p<=0)p+=sum;
if(p>sum)p-=sum;
}
}
}
printf("%s %d\n",Name[winnerid],num[maxid[n]]);
}
return 0;
}
二:成段更新(我当初看这个也看了好久才懂!其实说白了就是一个懒惰标记,更新的时候不要更新到底,比如buildtree(1,1,n).操作是区间加减某个数,询问是区间和。必须l到r增加add.我在update的时候呢,就找到l到r这段区间
直接将其区间和+add*(r-l+1).如果不是刚好就拆两段嘛.这样在该区间的父辈区间的区间和都是正确的。而子区间的区间和我们还没更新,是错误的。当要询问其子区间的区间和的时候,我们需要将add往下传递,也就是PushDown函数的作用了。
题意:操作有区间置1置2置3,最后询问区间和
思路:懒惰标记set,PushUp函数维护区间和.update的时候,修改更新区间的和,PushUp向上维护。PushDown函数向下传递懒惰标记同时更新子区间的和.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
struct ST
{
int l,r,set,key;
}st[maxn<<2];
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id]. r = r,st[id].set = 1;
st[id].key = r - l +1;
if(l == r)
{
return;
}
int mid = (l+r) >> 1;
buildtree(lson);
buildtree(rson);
}
void PushUp(int id)
{
st[id].key = st[id<<1].key + st[id<<1|1].key;
}
void PushDown(int id)
{
if(st[id].set != -1)
{
st[id<<1].set = st[id<<1|1].set = st[id].set;
st[id<<1].key = (st[id<<1].r - st[id<<1].l + 1)*st[id].set;
st[id<<1|1].key = (st[id<<1|1].r - st[id<<1|1].l + 1)*st[id].set;
st[id].set = -1;
}
}
void update(int id,int l,int r,int Set)
{
if(st[id].l == l && st[id].r == r)
{
st[id].set = Set;
st[id].key = (r - l + 1)*Set;
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,Set);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,Set);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,Set);
update(id<<1|1,st[id<<1|1].l,r,Set);
PushUp(id);
}
int query(int id,int l,int r)
{
if(st[id].l == l && st[id].r == r)
{
return st[id].key;
}
PushDown(id);
if(st[id<<1].r >= r)
{
return query(id<<1,l,r);
}
if(st[id<<1|1].l <= l)
{
return query(id<<1|1,l,r);
}
return query(id<<1,l,st[id<<1].r) + query(id<<1|1,st[id<<1|1].l,r);
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
for(int cas = 1;cas <= t;cas++)
{
int n; scanf("%d",&n);
buildtree(1,1,n);
int m; scanf("%d",&m);
for(int i = 1;i <= m;i++)
{
int u,v,ope;
scanf("%d%d%d",&u,&v,&ope);
update(1,u,v,ope);
}
printf("Case %d: The total value of the hook is %d.\n",cas,st[1].key);
}
return 0;
}
POJ3468 A Simple Problem with Integers
题意:操作区间加减,询问区间和
思路:update函数更新指定区间懒惰标记和和,PushUp函数向上传递,维护区间和。PushDown函数向下传递懒惰标记的同时更新子区间的区间和.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define LL long long int
#define maxn 100080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int A[maxn];
struct ST
{
int l,r;
LL key,add;
}st[maxn<<2];
void PushUp(int id)
{
st[id].key = st[id<<1].key + st[id<<1|1].key;
}
void PushDown(int id)
{
if(st[id].add)
{
st[id<<1].add += st[id].add;
st[id<<1|1].add += st[id].add;
st[id<<1].key += (st[id<<1].r - st[id<<1].l + 1)*st[id].add;
st[id<<1|1].key += (st[id<<1|1].r - st[id<<1|1].l + 1)*st[id].add;
st[id].add = 0;
}
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r;
if(l == r)
{
st[id].key = A[l];
return;
}
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
PushUp(id);
}
void update(int id,int l,int r,LL Add)
{
if(st[id].l == l && st[id].r == r)
{
st[id].add += Add;
st[id].key += (r - l + 1)*Add;
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,Add);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,Add);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,Add);
update(id<<1|1,st[id<<1|1].l,r,Add);
PushUp(id);
}
LL query(int id,int l,int r)
{
if(st[id].l == l && st[id].r == r) return st[id].key;
PushDown(id);
if(st[id<<1].r >= r) return query(id<<1,l,r);
if(st[id<<1|1].l <= l) return query(id<<1|1,l,r);
return query(id<<1,l,st[id<<1].r) + query(id<<1|1,st[id<<1|1].l,r);
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)==2)
{
for(int i = 1;i <= n;i++) scanf("%d",&A[i]);
buildtree(1,1,n);
char ope[2];int u,v,w;
for(int i = 1;i <= m;i++)
{
scanf("%s",ope);
if(ope[0] == 'Q')
{
scanf("%d%d",&u,&v);
printf("%lld\n",query(1,u,v));
}
else
{
scanf("%d%d%d",&u,&v,&w);
update(1,u,v,w);
}
}
}
return 0;
}
题意:往木条上贴海报,一张一张贴,求最后能看到的海报数目
思路:线段树的建立很好想,不过区间达到了1QW。而实际只有1W根棍子,也就是说2W个数就可以了
离散化要注意一点,比如有数据(1,10) (1,4) (6,10)还有数据(1,10) (1,4) (5,10)
问题出来了,第一组数据明明是可以看到3张海报的,这样只能看到2张海报了。解决方法是对坐标排序后,如果前后两个
的坐标差值大于1,就再插入一个点
比如1 4 6 10 离散后就是1 2 4 5 6 7 10 那么就是(1,7) (1,3) (5,7)
update的时候就是区间成段置值,更新颜色和懒惰标记,PushDown函数向下传递更新颜色和子区间懒惰标记,query函数就
递归到整个区间颜色是统一的地方为止
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 40080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int X[maxn<<1];
bool vis[maxn];
int ans;
struct ST
{
int l,r,set;
}st[maxn<<2];
struct Edge
{
int from,to;
}edge[10080];
void PushDown(int id)
{
if(st[id].set != - 1)
{
st[id<<1].set = st[id<<1|1].set = st[id].set;
st[id].set = -1;
}
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].set = 0;
if(l == r) return;
int mid = (l + r) >> 1;
buildtree(lson);
buildtree(rson);
}
void update(int id,int l,int r,int Set)
{
if(st[id].l == l && st[id].r == r)
{
st[id].set = Set;
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,Set);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,Set);
return;
}
update(id<<1,l,st[id<<1].r,Set);
update(id<<1|1,st[id<<1|1].l,r,Set);
}
void query(int id)
{
if(st[id].set != -1)
{
if(!vis[st[id].set] && st[id].set != 0)
{
ans++;
vis[st[id].set] = 1;
}
return;
}
PushDown(id);
query(id<<1);
query(id<<1|1);
}
int main()
{
//freopen("in.txt","r",stdin);
int t; scanf("%d",&t);
while(t--)
{
int n; scanf("%d",&n);
int k = 0;
for(int i = 0;i < n;i++)
{
scanf("%d%d",&edge[i].from,&edge[i].to);
X[k++] = edge[i].from;
X[k++] = edge[i].to;
}
sort(X,X+k);
int last = X[0],rear = k;
for(int i = 0;i < k;i++)
{
if(X[i] - last > 1) X[rear++] = last + 1;
last = X[i];
}
sort(X,X+rear);
buildtree(1,1,rear);
int cnt = 1;
for(int i = 0;i < n;i++)
{
update(1,lower_bound(X,X+rear,edge[i].from)-X+1,lower_bound(X,X+rear,edge[i].to)-X+1,cnt);
cnt++;
}
ans = 0;
memset(vis,0,sizeof(vis));
query(1);
printf("%d\n",ans);
}
return 0;
}
题意:
- U其实就是区间置1
- D其实就是区间置0
- I就是0到a-1 b+1到65535置0
- C就是区间取反(只剩中间部分)
- S就是区间取反(好像和C相同,整条)
- 输出最后的区间
思路:
因为有区间开闭,所以需要拆点
【: 2*u (:2*u+1 ):2*v-1 】:2*v
注意下异或操作。在update的时候,置0置1都比较好处理。orr操作的话,我们先看set是否为0或1,如果是只需st[id].set^=1;
否则st[id].orr ^= 1;query的时候,递归到st[id].set 不为-1时。用vis数组标记元素是否在集合中。
PS:注意下(3,3)这种数据
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 158888
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
bool vis[maxn];
struct ST
{
int l,r,set,orr;
}st[maxn<<2];
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].set = 0,st[id].orr = 0;
if(l == r) return;
int mid = (l+r)>>1;
buildtree(lson);
buildtree(rson);
}
void PushDown(int id)
{
if(st[id].set != -1)
{
st[id<<1].set = st[id<<1|1].set = st[id].set;
st[id<<1].orr = st[id<<1|1].orr = 0;
st[id].set = -1;
}
if(st[id].orr)
{
if(st[id<<1].set != -1) st[id<<1].set ^= 1;
else st[id<<1].orr ^= 1;
if(st[id<<1|1].set != -1) st[id<<1|1].set ^= 1;
else st[id<<1|1].orr ^= 1;
st[id].orr = 0;
}
}
void update(int id,int l,int r,int ope)
{
if(st[id].l == l && st[id].r == r)
{
if(ope != 2)
{
st[id].orr = 0;
st[id].set = ope;
return;
}
else
{
if(st[id].set != -1) st[id].set ^= 1;
else st[id].orr ^= 1;
return;
}
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,ope);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,ope);
return;
}
update(id<<1,l,st[id<<1].r,ope);
update(id<<1|1,st[id<<1|1].l,r,ope);
}
void query(int id)
{
if(st[id].set != -1)
{
if(st[id].set == 1)
{
for(int i = st[id].l;i <= st[id].r;i++) vis[i] =1;
}
return;
}
PushDown(id);
query(id<<1);
query(id<<1|1);
}
int main()
{
//freopen("in.txt","r",stdin);
char ope[2];
buildtree(1,1,140000);
while(scanf("%s",ope)!=EOF)
{
char left,righ;
int u,v;
getchar();
left = getchar();
scanf("%d,%d",&u,&v);
righ = getchar();
u++;v++;
if(left == '(') u = 2*u+1;
else u = u*2;
if(righ == ')') v = 2*v-1;
else v = 2*v;
if(ope[0] == 'U' && v>=u) update(1,u,v,1);
if(ope[0] == 'D' && v>=u) update(1,u,v,0);
if(ope[0] == 'S' && v>=u) update(1,u,v,2);
if(ope[0] == 'C')
{
update(1,1,u-1,0);
update(1,v+1,140000,0);
if(v>=u)update(1,u,v,2);
}
if(ope[0] == 'I')
{
update(1,1,u-1,0);
update(1,v+1,140000,0);
}
}
memset(vis,0,sizeof(vis));
query(1);
int ok = 1;
bool flag = true;
int first,last;
for(int i = 1;i <= 140000;i++)
{
if(vis[i])
{
flag = false;
if(vis[i-1]) last = i;
else first = i;
}
else
{
if(vis[i-1])
{
if((first)&1) printf("(%d,",first/2-1);
else printf("[%d,",first/2-1);
if((i-1)&1) printf("%d) ",i/2-1);
else printf("%d] ",i/2-1);
}
}
}
if(flag) printf("empty set");
printf("\n");
return 0;
}
POJ1436 Horizontally Visible Segments
题意:给出垂直线段,两条线段能连一条不经过其它线的水平线视为可见,3条两两可见的线段构成一三角形,求三角形数目
思路:将线段从左到右排序,query函数将该线段所能见到的线段放入其集合中,最后暴力枚举即可。(我代码WA,看了N久没看出毛病。几天后重新看还是觉得没问题!看出来的帮忙指正!)
/*
Y坐标要乘以2,比如(1,3)到(4,5)这两段中间是空着的,但是表示不出来
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
#define maxn 40080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
set <int> coll[maxn];
set <int> :: iterator it;
set <int> :: iterator itt;
struct Edge
{
int u,v,x;
}edge[maxn];
bool cmp(Edge a,Edge b)
{
return a.x < b.x;
}
struct ST
{
int l,r,set;
}st[maxn<<2];
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].set = 0;
if(l == r) return;
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
}
void PushDown(int id)
{
if(st[id].set > 0)
{
st[id<<1].set = st[id<<1|1].set = st[id].set;
st[id].set = 0;
}
}
void update(int id,int l,int r,int cnt)
{
if(st[id].l == l && st[id].r == r)
{
st[id].set = cnt;
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,cnt);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,cnt);
return;
}
update(id<<1,l,st[id<<1].r,cnt);
update(id<<1|1,st[id<<1|1].l,r,cnt);
}
void query(int id,int l,int r,int num)
{
if(st[id].set || l == r)
{
if(st[id].set != 0)
coll[num].insert(st[id].set);
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
query(id<<1,l,r,num);
return;
}
if(st[id<<1|1].l <= l)
{
query(id<<1|1,l,r,num);
return;
}
query(id<<1,l,st[id<<1].r,num);
query(id<<1|1,st[id<<1|1].l,r,num);
}
int main()
{
//freopen("in.txt","r",stdin);
int t; scanf("%d",&t);
while(t--)
{
int n; scanf("%d",&n);
buildtree(1,0,30000);
for(int i = 1;i <= n;i++)
{
coll[i].clear();
int x,y1,y2;
scanf("%d%d%d",&y1,&y2,&x);
//y1++;y2++;
y1 *= 2;y2 *= 2;
edge[i].u = y1,edge[i].v = y2,edge[i].x = x;
}
sort(edge+1,edge+n+1,cmp);
for(int i = 1;i <= n;i++)
{
query(1,edge[i].u,edge[i].v,i);
update(1,edge[i].u,edge[i].v,i);
}
int ans = 0;
for(int i = 3;i <= n;i++)
{
for(it = coll[i].begin();it != coll[i].end();it++)
{
int tt = *it;
for(itt = coll[tt].begin();itt != coll[tt].end();itt++)
{
if(coll[i].find(*itt) != coll[i].end()) ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
POJ2991 Crane
题意:初始N节木棍置于Y轴,木棍与木棍间有节点,可旋转,求每次旋转某节点后终点位置
思路:将线段看成向量,则旋转角度后的向量可以如此表示。证明很简单,
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
#define maxn 20080
#define PI acos(-1.0)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
double len[maxn];
int du[maxn];
struct ST
{
double x,y;
int l,r,add;
}st[maxn<<2];
void rotate(int id,int add)
{
double a = double(add)/180*PI;
double x = st[id].x,y = st[id].y;
st[id].x = cos(a)*x - sin(a)*y;
st[id].y = cos(a)*y +sin(a)*x;
}
void PushUp(int id)
{
st[id].x = st[id<<1].x + st[id<<1|1].x;
st[id].y = st[id<<1].y + st[id<<1|1].y;
}
void PushDown(int id)
{
if(st[id].add)
{
st[id<<1].add += st[id].add;
st[id<<1|1].add += st[id].add;
rotate(id<<1,st[id].add);
rotate(id<<1|1,st[id].add);
st[id].add = 0;
}
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].add = 0;
if(l == r)
{
st[id].x = 0,st[id].y = len[l];
return;
}
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
PushUp(id);
}
void update(int id,int l,int r,int add)
{
if(st[id].l == l && st[id].r == r)
{
st[id].add += add;
rotate(id,add);
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,add);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,add);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,add);
update(id<<1|1,st[id<<1|1].l,r,add);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
int cas = 0;
while(scanf("%d%d",&n,&m)==2)
{
if(cas != 0) printf("\n"); cas++;
for(int i = 0;i <= n;i++) du[i] = 180;
//du[0] = 90;
for(int i = 1;i <= n;i++) scanf("%lf",&len[i]);
buildtree(1,1,n);
for(int i = 1;i <= m;i++)
{
int u,d;
scanf("%d%d",&u,&d);
update(1,u+1,n,d-du[u+1]);
du[u+1] = d;
printf("%.2lf %.2lf\n",st[1].x,st[1].y);
}
}
return 0;
}
st[id].rkey = (st[id<<1|1].rkey == st[id<<1|1].r - st[id<<1|1].l +1? st[id<<1].rkey + st[id<<1|1].key : st[id<<1|1].rkey);
st[id].lkey = (st[id<<1].lkey == st[id<<1].r - st[id<<1].l + 1?st[id<<1].key + st[id<<1|1].lkey : st[id<<1].lkey);
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 200080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
struct ST
{
int l,r,key,lkey,rkey,set;
}st[maxn<<2];
inline int max(int a,int b,int c)
{
if(a<b) a = b;
if(a<c) a = c;
return a;
}
void PushUp(int id)
{
st[id].key = max(st[id<<1].key,st[id<<1|1].key,st[id<<1].rkey + st[id<<1|1].lkey);
st[id].rkey = (st[id<<1|1].rkey == st[id<<1|1].r - st[id<<1|1].l +1? st[id<<1].rkey + st[id<<1|1].key : st[id<<1|1].rkey);
st[id].lkey = (st[id<<1].lkey == st[id<<1].r - st[id<<1].l + 1?st[id<<1].key + st[id<<1|1].lkey : st[id<<1].lkey);
}
void PushDown(int id)
{
if(st[id].set != -1)
{
st[id<<1].set = st[id<<1|1].set = st[id].set;
st[id<<1].key = st[id<<1].rkey = st[id<<1].lkey = st[id].set?0:st[id<<1].r - st[id<<1].l + 1;
st[id<<1|1].key = st[id<<1|1].rkey = st[id<<1|1].lkey = st[id].set?0:st[id<<1|1].r - st[id<<1|1].l + 1;
st[id].set = -1;
}
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].set = 0;
st[id].lkey = st[id].rkey = st[id].key = r - l + 1;
if(l == r) return;
int mid = (l + r) >> 1;
buildtree(lson);
buildtree(rson);
}
void update(int id,int l,int r,int ope)
{
if(st[id].l == l && st[id].r == r)
{
st[id].set = ope;
st[id].key = st[id].lkey = st[id].rkey = ope?0:r - l + 1;
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,ope);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,ope);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,ope);
update(id<<1|1,st[id<<1|1].l,r,ope);
PushUp(id);
}
int query(int id,int l,int r,int cost)
{
if(l == r) return l;
PushDown(id);
if(st[id<<1].key >= cost)
{
return query(id<<1,l,st[id<<1].r,cost);
}
else if(st[id<<1].rkey + st[id<<1|1].lkey >= cost)
{
return st[id<<1].r - st[id<<1].rkey + 1;
}
else return query(id<<1|1,st[id<<1|1].l,r,cost);
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m,pos;
while(scanf("%d%d",&n,&m)==2)
{
buildtree(1,1,n);
int ope,u,v;
for(int i=1;i<=m;i++)
{
scanf("%d",&ope);
if(ope==1)
{
scanf("%d",&u);
if(u>st[1].key)printf("%d\n",0);
else
{
pos=query(1,1,n,u);
printf("%d\n",pos);
update(1,pos,pos+u-1,1);
}
}
else
{
scanf("%d%d",&u,&v);
update(1,u,u+v-1,0);
}
}
}
return 0;
}
HDU3308 LCIS
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int A[maxn];
struct ST
{
int l,r,key,lkey,rkey;
}st[maxn<<2];
inline int max(int a,int b,int c)
{
if(a<b) a = b;
if(a<c) a = c;
return a;
}
inline int min(int a,int b)
{
return a>b?b:a;
}
void PushUp(int id)
{
st[id].key = max(st[id<<1].key,st[id<<1|1].key,A[st[id<<1|1].l]>A[st[id<<1].r]?st[id<<1|1].lkey + st[id<<1].rkey:0);
st[id].rkey = max(st[id<<1|1].rkey,(st[id<<1|1].rkey == st[id<<1|1].r - st[id<<1|1].l + 1 && A[st[id<<1|1].l]>A[st[id<<1].r])?st[id<<1].rkey + st[id<<1|1].key : 0);
st[id].lkey = max(st[id<<1].lkey,(st[id<<1].lkey == st[id<<1].r - st[id<<1].l + 1 && A[st[id<<1|1].l]>A[st[id<<1].r])? st[id<<1].key + st[id<<1|1].lkey:0);
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r;
if(l == r)
{
st[id].key = st[id].lkey = st[id].rkey = 1;
return;
}
int mid = (l+r)>>1;
buildtree(lson);
buildtree(rson);
PushUp(id);
}
int query(int id,int l,int r)
{
if(st[id].l == l && st[id].r == r) return st[id].key;
if(st[id<<1].r >= r) return query(id<<1,l,r);
if(st[id<<1|1].l <= l) return query(id<<1|1,l,r);
int left = min(st[id<<1].rkey,st[id<<1].r - l + 1);
int right = min(st[id<<1|1].lkey,r - st[id<<1|1].l + 1);
int ans = max(query(id<<1,l,st[id<<1].r),query(id<<1|1,st[id<<1|1].l,r));
ans = max(ans,A[st[id<<1|1].l] > A[st[id<<1].r]?left + right:0);
return ans;
}
void update(int id,int pos,int newk)
{
if(st[id].l == pos && st[id].r == pos)
{
A[pos] = newk;
return;
}
if(st[id<<1].r >= pos) update(id<<1,pos,newk);
else update(id<<1|1,pos,newk);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int t; scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++) scanf("%d",&A[i]);
buildtree(1,1,n);
char ope[2];int u,v;
for(int i = 1;i <= m;i++)
{
scanf("%s%d%d",ope,&u,&v);
if(ope[0] == 'Q') printf("%d\n",query(1,u+1,v+1));
else update(1,u+1,v);
}
}
return 0;
}
HDU3397 Sequence operation
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int A[maxn];
struct ST
{
int l,r,sum,lkey,rkey,key,set,orr;
}st[maxn<<2];
inline int max(int a,int b,int c)
{
if(a<b) a = b;
if(a<c) a = c;
return a;
}
inline int max(int a,int b)
{
return a>b?a:b;
}
inline int min(int a,int b)
{
return a>b?b:a;
}
void PushDown(int id)
{
if(st[id].set != -1)
{
st[id<<1].orr = st[id<<1|1].orr = 0;
st[id<<1].set = st[id<<1|1].set = st[id].set;
st[id<<1].key = st[id<<1].lkey = st[id<<1].rkey = st[id<<1].sum = st[id].set?st[id<<1].r - st[id<<1].l + 1:0;
st[id<<1|1].key = st[id<<1|1].lkey = st[id<<1|1].rkey = st[id<<1|1].sum = st[id].set?st[id<<1|1].r - st[id<<1|1].l + 1:0;
st[id].set = -1;
}
if(st[id].orr)
{
if(st[id<<1].set!=-1) st[id<<1].set ^= 1;
else st[id<<1].orr ^= 1;
if(st[id<<1|1].set!=-1) st[id<<1|1].set ^= 1;
else st[id<<1].orr ^= 1;
}
}
void PushUp(int id)
{
st[id].key = max(st[id<<1].key,st[id<<1|1].key,st[id<<1].rkey + st[id<<1|1].lkey);
st[id].lkey = max(st[id<<1].lkey,st[id<<1].lkey == st[id<<1].r - st[id<<1].l + 1?st[id<<1].sum + st[id<<1|1].lkey:0);
st[id].rkey = max(st[id<<1|1].rkey,st[id<<1|1].rkey == st[id<<1|1].r - st[id<<1|1].l + 1?st[id<<1|1].sum + st[id<<1].rkey:0);
st[id].sum = st[id<<1].sum + st[id<<1|1].sum;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].set = -1,st[id].orr = 0;
if(l == r)
{
st[id].key = st[id].lkey = st[id].rkey = st[id].sum = st[id].set = A[l];
return;
}
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
PushUp(id);
}
void update(int id,int l,int r,int ope)
{
if(st[id].l == l && st[id].r == r)
{
if(ope == 0)
{
st[id].set = 0;st[id].orr = 0;
st[id].key = st[id].lkey = st[id].rkey = st[id].sum = 0;
return;
}
if(ope == 1)
{
st[id].set = 1;st[id].orr = 0;
st[id].key = st[id].lkey = st[id].rkey = st[id].sum = r - l + 1;
return;
}
if(ope == 2)
{
if(st[id].set != -1)
{
st[id].set ^= 1;st[id].orr = 0;
st[id].key = st[id].lkey = st[id].rkey = st[id].sum = st[id].set?r - l + 1:0;
return;
}
}
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,ope);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,ope);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,ope);
update(id<<1|1,st[id<<1|1].l,r,ope);
PushUp(id);
}
int query(int id,int l,int r,int ope)
{
if(st[id].l == l && st[id].r == r)
{
if(ope == 3) return st[id].sum;
if(ope == 4) return st[id].key;
}
PushDown(id);
if(st[id<<1].r >= r)
{
return query(id<<1,l,r,ope);
}
if(st[id<<1|1].l <= l)
{
return query(id<<1|1,l,r,ope);
}
if(ope == 3)
return query(id<<1,l,st[id<<1].r,ope) + query(id<<1|1,st[id<<1|1].l,r,ope);
if(ope == 4)
{
int left = query(id<<1,l,st[id<<1].r,ope);
int right = query(id<<1|1,st[id<<1|1].l,r,ope);
int ans = min(st[id<<1].r - l +1,st[id<<1].rkey) + min(r- st[id<<1|1].l +1,st[id<<1|1].lkey);
return max(ans,left,right);
}
}
int main()
{
//freopen("in.txt","r",stdin);
int t; scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++) scanf("%d",&A[i]);
buildtree(1,1,n);
for(int i = 1;i <= m;i++)
{
int ope,u,v;
scanf("%d%d%d",&ope,&u,&v);
if(ope == 3 || ope == 4) printf("%d\n",query(1,u+1,v+1,ope));
else update(1,u+1,v+1,ope);
}
}
return 0;
}
HDU2871 Memory Control
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define maxn 50080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
inline int max(int a,int b)
{
return a>b?a:b;
}
inline int max(int a,int b,int c)
{
if(a < b) a = b;
if(a < c) a = c;
return a;
}
inline int min(int a,int b)
{
return a>b?b:a;
}
struct ST
{
int l,r,key,lkey,rkey,set;
}st[maxn<<2];
struct Edge
{
int u,v;
Edge(){}
Edge(int uu,int vv)
{
u = uu;v = vv;
}
};
vector <Edge> coll;
int binary(int x)
{
int l = 0,r = coll.size()-1;
while(l <= r)
{
int mid = (l + r)>>1;
if(coll[mid].u <= x) l = mid+1;
else r = mid-1;
}
return l;
}
void PushDown(int id)
{
if(st[id].set != -1)
{
st[id<<1].set = st[id<<1|1].set = st[id].set;
st[id<<1].key = st[id<<1].lkey = st[id<<1].rkey = st[id].set?0:st[id<<1].r - st[id<<1].l + 1;
st[id<<1|1].key = st[id<<1|1].lkey = st[id<<1|1].rkey = st[id].set?0:st[id<<1|1].r - st[id<<1|1].l + 1;
st[id].set = -1;
}
}
void PushUp(int id)
{
st[id].key = max(st[id<<1].key,st[id<<1|1].key,st[id<<1].rkey + st[id<<1|1].lkey);
st[id].lkey = max(st[id<<1].lkey,st[id<<1].lkey == st[id<<1].r - st[id<<1].l + 1?st[id<<1].key + st[id<<1|1].lkey:0);
st[id].rkey = max(st[id<<1|1].rkey,st[id<<1|1].rkey == st[id<<1|1].r - st[id<<1|1].l + 1?st[id<<1|1].key + st[id<<1].rkey:0);
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].set = 0;
st[id].key = st[id].lkey = st[id].rkey = r - l + 1;
if(l == r) return;
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
}
void update(int id,int l,int r,int ope)//清空
{
if(st[id].l == l && st[id].r == r)
{
st[id].set = ope;
st[id].key = st[id].lkey = st[id].rkey = ope?0:r - l + 1;
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,ope);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,ope);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,ope);
update(id<<1|1,st[id<<1|1].l,r,ope);
PushUp(id);
}
int query(int id,int l,int r,int cost)
{
if(l == r) return l;
PushDown(id);
if(st[id<<1].key >= cost)
return query(id<<1,l,st[id<<1].r,cost);
if(st[id<<1].rkey + st[id<<1|1].lkey >= cost)
return st[id<<1].r - st[id<<1].rkey + 1;
return query(id<<1|1,st[id<<1|1].l,r,cost);
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)==2)
{
buildtree(1,1,n);
coll.clear();
int u; char ope[10];
for(int i = 1;i <= m;i++)
{
scanf("%s",ope);
if(ope[0] != 'R') scanf("%d",&u);
if(ope[0] == 'R')
{
coll.clear();
update(1,1,n,0);
printf("Reset Now\n");
}
if(ope[0] == 'N')
{
if(st[1].key >= u)
{
int s = query(1,1,n,u);
update(1,s,s+u-1,1);
//二分找地方插入
if(coll.size() == 0) coll.push_back(Edge(s,s+u-1));
else
{
int hehe = binary(s);
coll.insert(coll.begin()+hehe,Edge(s,s+u-1));//插入比如2就是2这个变成新的,其他后推
}
printf("New at %d\n",s);
}
else printf("Reject New\n");
}
if(ope[0] == 'F')
{
int pos = binary(u)-1;
if(pos < coll.size() && coll[pos].u <= u && coll[pos].v >= u)
{
update(1,coll[pos].u,coll[pos].v,0);
printf("Free from %d to %d\n",coll[pos].u,coll[pos].v);
coll.erase(coll.begin()+pos);
}
else printf("Reject Free\n");
}
if(ope[0] == 'G')
{
if(coll.size() > u - 1)
printf("Get at %d\n",coll[u-1].u);
else printf("Reject Get\n");
}
}
printf("\n");
}
return 0;
}
HDU1540 Tunnel Warfare
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 50080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int pre[maxn];
struct ST
{
int l,r,lkey,rkey;
}st[maxn<<2];
inline int max(int a,int b)
{
return a>b?a:b;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r;
st[id].lkey = st[id].rkey = r-l+1;
if(l == r) return;
int mid = (l +r) >> 1;
buildtree(lson);
buildtree(rson);
}
void PushUp(int id)
{
st[id].lkey = max(st[id<<1].lkey,st[id<<1].r - st[id<<1].l + 1==st[id<<1].lkey?st[id<<1].lkey + st[id<<1|1].lkey:0);
st[id].rkey = max(st[id<<1|1].rkey,st[id<<1|1].r - st[id<<1|1].l + 1 == st[id<<1|1].rkey?st[id<<1].rkey + st[id<<1|1].rkey:0);
}
void update(int id,int pos,int ope)
{
if(st[id].l == pos && st[id].r == pos)
{
st[id].lkey = st[id].rkey = ope;
return;
}
if(st[id<<1].r >= pos) update(id<<1,pos,ope);
if(st[id<<1|1].l <= pos) update(id<<1|1,pos,ope);
PushUp(id);
}
int query(int id,int l,int r,int ope)
{
if(st[id].l == l && st[id].r == r)
{
if(ope == 1) return st[id].lkey;
else return st[id].rkey;
}
if(st[id<<1].r >= r)
{
return query(id<<1,l,r,ope);
}
if(st[id<<1|1].l <= l)
{
return query(id<<1|1,l,r,ope);
}
int ans1 = query(id<<1,l,st[id<<1].r,ope);
int ans2 = query(id<<1|1,st[id<<1|1].l,r,ope);
if(ope == 1)
{
if(ans1 == st[id<<1].r - l + 1) return ans1+ans2;
return ans1;
}
else
{
if(ans2 == r - st[id<<1|1].l + 1) return ans1+ans2;
return ans2;
}
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)==2)
{
buildtree(1,1,n);
memset(pre,0,sizeof(pre));
char ope[2];int u,last = 0;
for(int i = 1;i <= m;i++)
{
scanf("%s",ope);
if(ope[0] != 'R') scanf("%d",&u);
if(ope[0] == 'D')
{
pre[u] = last;
last = u;
update(1,u,0);
}
if(ope[0] == 'Q')
{
int ans = query(1,1,u,2) + query(1,u,n,1) - 1;
printf("%d\n",ans>0?ans:0);
}
if(ope[0] == 'R')
{
update(1,last,1);
last = pre[last];
}
}
}
return 0;
}
四:扫描线
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 280
#define lson id<<1,l,mid
#define rson id<<1|1,mid,r
double X[maxn];
struct ST
{
int l,r,add;
double len;
}st[maxn<<2];
struct Edge
{
double x1,x2,y;
int add;
}edge[maxn];
bool cmp(Edge a,Edge b)
{
return a.y < b.y;
}
void PushUp(int id)
{
if(st[id].add >= 1) st[id].len = X[st[id].r] - X[st[id].l];
else if(st[id].l + 1 != st[id].r) st[id].len = st[id<<1].len + st[id<<1|1].len;
else st[id].len = 0;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].len = 0;
if(l + 1 == r) return;
int mid = (l+r) >> 1;
buildtree(lson);
buildtree(rson);
}
void update(int id,int l,int r,int add)
{
if(st[id].l == l && st[id].r == r)
{
st[id].add += add;
if(st[id].add >= 1) st[id].len = X[r] - X[l];
else if(l + 1 != r) st[id].len = st[id<<1].len + st[id<<1|1].len;
else st[id].len = 0;
return;
}
if(st[id<<1].r >= r)
{
update(id<<1,l,r,add);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,add);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,add);
update(id<<1|1,st[id<<1|1].l,r,add);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int n,cas = 0;
while(scanf("%d",&n)!=EOF && n)
{
double x1,y1,x2,y2;
int k = 0,cnt = 0;
for(int i = 1;i <= n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
edge[cnt].add = 1;
edge[cnt].x1 = x1;
edge[cnt].x2 = x2;
edge[cnt++].y = y1;
edge[cnt].add = -1;
edge[cnt].x1 = x1;
edge[cnt].x2 = x2;
edge[cnt++].y = y2;
X[k++] = x1;
X[k++] = x2;
}
sort(edge,edge+cnt,cmp);
sort(X,X+k);
buildtree(1,0,k-1);
double len = 0,ans = 0,lasty = 0;
for(int i = 0;i < cnt;i++)
{
ans += len*(edge[i].y - lasty);
int u = lower_bound(X,X+k,edge[i].x1) - X;
int v = lower_bound(X,X+k,edge[i].x2) - X;
update(1,u,v,edge[i].add);
len = st[1].len;
lasty = edge[i].y;
}
printf("Test case #%d\n",++cas);
printf("Total explored area: %.2lf\n\n",ans);
}
return 0;
}
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define maxn 10080
#define lson id<<1,l,mid
#define rson id<<1|1,mid,r
int X[maxn];
struct ST
{
int l,r,lcov,rcov,sum,add,len;
}st[maxn<<2];
struct Edge
{
int x1,x2,y;
int add;
}edge[maxn];
bool cmp(Edge a,Edge b)
{
return a.y < b.y;
}
void PushUp(int id)
{
if(st[id].add > 0)
{
st[id].len = X[st[id].r] - X[st[id].l];
st[id].lcov = st[id].rcov = 1;
st[id].sum = 1;
}
else if(st[id].l + 1 != st[id].r)
{
st[id].lcov = st[id<<1].lcov;
st[id].rcov = st[id<<1|1].rcov;
st[id].len = st[id<<1].len + st[id<<1|1].len;
st[id].sum = st[id<<1].sum + st[id<<1|1].sum - (st[id<<1].rcov && st[id<<1|1].lcov);
}
else
{
st[id].len = st[id].sum = st[id].lcov = st[id].rcov = 0;
}
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].lcov = st[id].rcov = st[id].sum = st[id].len = st[id].add = 0;
if(l + 1 == r) return;
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
}
void update(int id,int l,int r,int add)
{
if(st[id].l == l && st[id].r == r)
{
st[id].add += add;
PushUp(id);
return;
}
if(st[id<<1].r >= r)
{
update(id<<1,l,r,add);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,add);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,add);
update(id<<1|1,st[id<<1|1].l,r,add);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF && n)
{
int cnt = 0,k = 0;
for(int i = 0;i < n;i++)
{
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
edge[cnt].x1 = x1;
edge[cnt].x2 = x2;
edge[cnt].y = y1;
edge[cnt++].add = 1;
edge[cnt].x1 = x1;
edge[cnt].x2 = x2;
edge[cnt].y = y2;
edge[cnt++].add = -1;
X[k++] = x1;
X[k++] = x2;
}
sort(edge,edge+cnt,cmp);
sort(X,X+k);
buildtree(1,0,k-1);
int ans = 0,lastlen = 0,lasty = 0;
for(int i = 0;i < cnt;i++)
{
int u = lower_bound(X,X+k,edge[i].x1) - X;
int v = lower_bound(X,X+k,edge[i].x2) - X;
ans += st[1].sum* (edge[i].y - lasty)*2;
update(1,u,v,edge[i].add);
ans += abs(st[1].len - lastlen);
lastlen = st[1].len;
lasty = edge[i].y;
}
printf("%d\n",ans);
}
return 0;
}
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 200080
#define lson id<<1,l,mid
#define rson id<<1|1,mid,r
#define LL long long int
int X[maxn];
struct ST
{
int l,r,add,len;
}st[maxn<<2];
struct Edge
{
int x1,x2,y,vis;
}edge[10*maxn];
bool cmp(Edge a,Edge b)
{
return a.y < b.y;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r;
st[id].len = st[id].add = 0;
if(l + 1 == r) return;
int mid = (l + r) >> 1;
buildtree(lson);
buildtree(rson);
}
void PushUp(int id)
{
if(st[id].add > 0) st[id].len = X[st[id].r] - X[st[id].l];
else if(st[id].l + 1 != st[id].r)
{
st[id].len = st[id<<1].len + st[id<<1|1].len;
}
else st[id].len = 0;
}
void update(int id,int l,int r,int add)
{
if(st[id].l == l && st[id].r == r)
{
st[id].add += add;
PushUp(id);
return;
}
if(st[id<<1].r >= r)
{
update(id<<1,l,r,add);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,add);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,add);
update(id<<1|1,st[id<<1|1].l,r,add);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF && n)
{
int k = 0,cnt = 0;
for(int i = 1;i <= n;i++)
{
int x1,y1,x2,y2,x3,y3,x4,y4;
scanf("%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
X[k++] = x1;X[k++] = x2;X[k++] = x3;X[k++] = x4;
if(x2 > x1 && y3 > y1)
{
edge[cnt].vis = 1;
edge[cnt].x1 = x1;
edge[cnt].x2 = x2;
edge[cnt++].y = y1;
edge[cnt].vis = -1;
edge[cnt].x1 = x1;
edge[cnt].x2 = x2;
edge[cnt++].y = y3;
}
if(x3 > x1 && y2 > y1)
{
edge[cnt].vis = 1;
edge[cnt].x1 = x1;
edge[cnt].x2 = x3;
edge[cnt++].y = y1;
edge[cnt].vis = -1;
edge[cnt].x1 = x1;
edge[cnt].x2 = x3;
edge[cnt++].y = y2;
}
if(x4 > x3 && y2 > y4)
{
edge[cnt].vis = 1;
edge[cnt].x1 = x3;
edge[cnt].x2 = x4;
edge[cnt++].y = y4;
edge[cnt].vis = -1;
edge[cnt].x1 = x3;
edge[cnt].x2 = x4;
edge[cnt++].y = y2;
}
if(x2 > x4 && y2 > y3)
{
edge[cnt].vis = 1;
edge[cnt].x1 = x4;
edge[cnt].x2 = x2;
edge[cnt++].y = y3;
edge[cnt].vis = - 1;
edge[cnt].x1 = x4;
edge[cnt].x2 = x2;
edge[cnt++].y = y2;
}
}
sort(edge,edge+cnt,cmp);
sort(X,X+k);
buildtree(1,0,k-1);
LL ans = 0,lastlen = 0,lasty = 0;
for(int i = 0;i < cnt;i++)
{
ans += lastlen * (LL(edge[i].y) - lasty);
int u = lower_bound(X,X+k,edge[i].x1)-X;
int v = lower_bound(X,X+k,edge[i].x2)-X;
update(1,u,v,edge[i].vis);
lastlen = st[1].len;
lasty = edge[i].y;
}
printf("%I64d\n",ans);
}
return 0;
}
思路:离散Z轴,对每一个值,循环找到跨越这个层的长方体,添边排序,扫描线求面积交。对离散的Z逐层遍历,*下高度差,叠加就是体积交了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 2080
#define lson id<<1,l,mid
#define rson id<<1|1,mid,r
#define LL long long int
LL X[maxn],Z[maxn];
bool val[maxn];
struct ST
{
int l,r,add,len1,len2,len3;
}st[maxn<<2];
struct REC
{
LL x1,y1,x2,y2,z1,z2;
}rec[maxn];
struct Edge
{
LL x1,x2,y,vis;
}edge[maxn];
bool cmp(Edge a,Edge b)
{
return a.y < b.y;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].add = st[id].len1 = st[id].len2 = st[id].len3= 0;
if(l + 1 == r) return;
int mid = (l+r) >> 1;
buildtree(lson);
buildtree(rson);
}
void PushUp(int id)
{
if(st[id].add > 2) st[id].len1 = st[id].len2 = st[id].len3 = X[st[id].r] - X[st[id].l];
else if(st[id].add > 1)
{
st[id].len1 = st[id].len2 = X[st[id].r] - X[st[id].l];
if(st[id].l + 1 == st[id].r) st[id].len3 = 0;
else st[id].len3 = st[id<<1].len1 + st[id<<1|1].len1;
}
else if(st[id].add > 0)
{
st[id].len1 = X[st[id].r] - X[st[id].l];
if(st[id].l + 1 != st[id].r)
{
st[id].len2 = st[id<<1].len1 + st[id<<1|1].len1;
st[id].len3 = st[id<<1].len2 + st[id<<1|1].len2;
}
else st[id].len2 = st[id].len3 = 0;
}
else
{
if(st[id].l + 1 != st[id].r)
{
st[id].len1 = st[id<<1].len1 + st[id<<1|1].len1;
st[id].len2 = st[id<<1].len2 + st[id<<1|1].len2;
st[id].len3 = st[id<<1].len3 + st[id<<1|1].len3;
}
else st[id].len1 = st[id].len2 = st[id].len3 = 0;
}
}
void update(int id,int l,int r,int add)
{
if(st[id].l == l && st[id].r == r)
{
st[id].add += add;
PushUp(id);
return;
}
if(st[id<<1].r >= r)
{
update(id<<1,l,r,add);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,add);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,add);
update(id<<1|1,st[id<<1|1].l,r,add);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int t; scanf("%d",&t);
for(int cas = 1;cas <= t;cas++)
{
int n; scanf("%d",&n);
int kx = 0,kz = 0;
memset(val,0,sizeof(val));
for(int i = 1;i <= n;i++)
{
LL x1,y1,z1,x2,y2,z2;
scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&x1,&y1,&z1,&x2,&y2,&z2);
X[kx++] = x1;
X[kx++] = x2;
if(!val[z1+520]){Z[kz++] = z1;val[z1+520] = 1;}
if(!val[z2+520]){Z[kz++] = z2;val[z2+520]=1;}
rec[i].x1 = x1;
rec[i].x2 = x2;
rec[i].y1= y1;
rec[i].y2 = y2;
rec[i].z1 = z1;
rec[i].z2 = z2;
}
sort(X,X+kx);
sort(Z,Z+kz);
//接下来是遍历每一层,筛选能覆盖该层的矩形,添边。
//筛完之后边排序,然后就是矩形面积交的问题了、
LL ans = 0,area = 0;
for(int i = 0;i < kz;i++)
{
if(i)ans += area*(Z[i] - Z[i-1]);
int zz = Z[i];int cnt = 0;
for(int j = 1;j <= n;j++)
{
if(rec[j].z1 <= zz && rec[j].z2 > zz)
{
edge[cnt].x1 = rec[j].x1;
edge[cnt].x2 = rec[j].x2;
edge[cnt].y = rec[j].y1;
edge[cnt++].vis = 1;
edge[cnt].x1 = rec[j].x1;
edge[cnt].x2 = rec[j].x2;
edge[cnt].y = rec[j].y2;
edge[cnt++].vis = -1;
}
}
sort(edge,edge+cnt,cmp);
buildtree(1,0,kx-1);
area = 0;
LL lastlen = 0,lasty = 0;
for(int j = 0;j < cnt;j++)
{
area += lastlen*(edge[j].y - lasty);
int u = lower_bound(X,X+kx,edge[j].x1) - X;
int v = lower_bound(X,X+kx,edge[j].x2) - X;
update(1,u,v,edge[j].vis);
lastlen = st[1].len3;
lasty = edge[j].y;
}
}
printf("Case %d: %I64d\n",cas,ans);
}
return 0;
}
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 20080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define LL long long int
LL X[maxn];
struct ST
{
int l,r,key,add;
}st[maxn<<2];
struct Edge
{
LL x1,x2,y,vis;
}edge[maxn];
bool cmp(Edge a,Edge b)
{
if(a.y > b.y) return 0;
if(a.y < b.y) return 1;
if(a.y == b.y)
{
return a.vis >= b.vis;
}
}
inline LL max(LL a,LL b)
{
return a>b?a:b;
}
void PushDown(int id)
{
if(st[id].add)
{
st[id<<1].add += st[id].add;
st[id<<1|1].add += st[id].add;
st[id<<1].key += st[id].add;
st[id<<1|1].key += st[id].add;
st[id].add = 0;
}
}
void PushUp(int id)
{
st[id].key = max(st[id<<1].key,st[id<<1|1].key);
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].key = st[id].add = 0;
if(l == r) return;
int mid = (l + r)>>1;
buildtree(lson);
buildtree(rson);
}
void update(int id,int l,int r,int add)
{
if(st[id].l == l && st[id].r == r)
{
st[id].add += add;
st[id].key += add;
return;
}
PushDown(id);
if(st[id<<1].r >= r)
{
update(id<<1,l,r,add);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,add);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,add);
update(id<<1|1,st[id<<1|1].l,r,add);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
LL n,w,h;
while(scanf("%lld%lld%lld",&n,&w,&h)==3)
{
int k = 0,cnt = 0;
for(int i = 1;i <= n;i++)
{
LL x,y,add;
scanf("%lld%lld%lld",&x,&y,&add);
X[k++] = x;
X[k++] = x+w-1;
edge[cnt].x1 = x;
edge[cnt].x2 = x+w-1;
edge[cnt].y = y;
edge[cnt++].vis = add;
edge[cnt].x1 = x;
edge[cnt].x2 = x+w-1;
edge[cnt].y = y+h-1;
edge[cnt++].vis = -add;
}
sort(X,X+k);
sort(edge,edge+cnt,cmp);
buildtree(1,0,k-1);
int ans = 0;
for(int i = 0;i < cnt;i++)
{
int u = lower_bound(X,X+k,edge[i].x1) - X;
int v = lower_bound(X,X+k,edge[i].x2) - X;
update(1,u,v,edge[i].vis);
ans = max(ans,st[1].key);
}
printf("%d\n",ans);
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
#define maxn 200080
#define inf 0x3f3f3f3f
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int X[maxn],Y[maxn],n;
struct ST
{
int l,r,sum;
}st[maxn<<2];
struct Point
{
int x,y;
}ppoint[maxn];
int binary(int x,int y)
{
int l = 1,r = n;
while(l < r)
{
int mid = ( l + r ) >> 1;
if(ppoint[mid].x > x || (ppoint[mid].x == x && ppoint[mid].y <= y)) r = mid;
else l = mid+1;
}
return l;
}
inline int max(int a,int b)
{
return a>b?a:b;
}
bool cmp(Point a,Point b)
{
if(a.x < b.x) return 1;
if(a.x > b.x) return 0;
if(a.x == b.x) return a.y > b.y;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].sum = 0;
if(l == r) return;
int mid = (l + r) >> 1;
buildtree(lson);
buildtree(rson);
}
void PushUp(int id)
{
st[id].sum = st[id<<1].sum + st[id<<1|1].sum;
}
void update(int id,int pos)
{
if(st[id].l == pos && st[id].r == pos)
{
st[id].sum += 1;
return;
}
if(st[id<<1].r >= pos) update(id<<1,pos);
else update(id<<1|1,pos);
PushUp(id);
}
int query(int id,int l,int r)
{
if(st[id].l == l && st[id].r == r)
{
return st[id].sum;
}
if(st[id<<1].r >= r)
{
return query(id<<1,l,r);
}
if(st[id<<1|1].l <= l)
{
return query(id<<1|1,l,r);
}
return query(id<<1,l,st[id<<1].r) + query(id<<1|1,st[id<<1|1].l,r);
}
vector <int> p[maxn];
vector <int> ans[maxn];
vector <int> final;
set <int> coll;
set <int> :: iterator it;
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF && n)
{
int k = 0;
for(int i = 1;i <= n;i++)
{
scanf("%d%d",&ppoint[i].x,&ppoint[i].y);
X[k] = ppoint[i].x; Y[k++] = ppoint[i].y;
}
sort(X,X+k); sort(Y,Y+k);
for(int i = 0;i < k;i++)
{
p[i].clear(); ans[i].clear();
}
ans[n].clear();
for(int i = 1;i <= n;i++)
{
int x = lower_bound(X,X+k,ppoint[i].x) - X;
int y = lower_bound(Y,Y+k,ppoint[i].y) - Y;
p[x].push_back(y);
ppoint[i].x = x;
ppoint[i].y = y;
}
sort(ppoint+1,ppoint+n+1,cmp);
buildtree(1,0,k-1);
int s = 1,t = 1,lastx = inf;
for(int i = 1;i <= n;i++)
{
if(i!=1 && ppoint[i].x != lastx)
{
for(int j = s;j <= t;j++)
{
update(1,ppoint[j].y);
}
s = t = i;
}
t = i; lastx = ppoint[i].x;
int lt = ppoint[i].y < k-1?query(1,ppoint[i].y+1,k-1):0;
int ld = ppoint[i].y>0?query(1,0,ppoint[i].y-1):0;
ans[i].push_back(lt);
ans[i].push_back(ld);
}
buildtree(1,0,k-1);
s = t = n,lastx = inf;
for(int i = n;i >= 1;i--)
{
if(i!=n && ppoint[i].x != lastx)
{
for(int j = s;j >= t;j--)
{
update(1,ppoint[j].y);
}
s = t = i;
}
t = i; lastx = ppoint[i].x;
int rt = ppoint[i].y < k-1?query(1,ppoint[i].y+1,k-1):0;
int rd = ppoint[i].y>0?query(1,0,ppoint[i].y-1):0;
ans[i].push_back(rt);
ans[i].push_back(rd);
}
int pos = 1,Ans = -inf;
for(int i = 0;i < k;i++)
{
int maxs = -1;
for(int j = 0;j < p[i].size();j++)
{
int pnum = binary(i,p[i][j]);
if(maxs == -1) maxs = ans[pnum][1] + ans[pnum][2];
if(ans[pnum][1] + ans[pnum][2] < maxs)
{
maxs = ans[pnum][1] + ans[pnum][2];
}
}
if(maxs == Ans)
{
final.push_back(i);
}
if(maxs > Ans)
{
Ans = maxs;
final.clear();
final.push_back(i);
}
}
printf("Stan: %d; ",Ans);
printf("Ollie: ");
coll.clear();
for(int i = 0;i < final.size();i++)
{
int u = final[i];
Ans = -1;
for(int j = 0;j < p[u].size();j++)
{
int pnum = binary(u,p[u][j]);
Ans = max(Ans,ans[pnum][0]+ans[pnum][3]);
}
coll.insert(Ans);
}
int cnt = 0,sum = coll.size();
for(it = coll.begin();it != coll.end();it++)
{
printf("%d",*it);
cnt++;
if(cnt == sum)printf(";\n");
else printf(" ");
}
}
return 0;
}
HDU3255 Farming
题意:每个工人会在矩形区域种蔬菜,同快土地如果被多种蔬菜覆盖只算最贵的蔬菜。求这块土地能得到的最大价值
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 60080
#define lson id<<1,l,mid
#define rson id<<1|1,mid,r
#define LL long long int
int X[maxn],Z[208];
struct ST
{
int l,r,len,add;
}st[maxn<<2];
struct REC
{
int x1,x2,y1,y2,z1,z2;
}rec[maxn];
struct Edge
{
int x1,x2,y,vis;
}edge[maxn];
bool cmp(Edge a,Edge b)
{
return a.y < b.y;
}
void PushUp(int id)
{
if(st[id].add > 0) st[id].len = X[st[id].r] - X[st[id].l];
else if(st[id].l + 1 == st[id].r) st[id].len = 0;
else st[id].len = st[id<<1].len + st[id<<1|1].len;
}
void buildtree(int id,int l,int r)
{
st[id].l = l,st[id].r = r,st[id].len = st[id].add = 0;
if(l + 1 == r) return;
int mid = (l + r) >> 1;
buildtree(lson);
buildtree(rson);
}
void update(int id,int l,int r,int add)
{
if(st[id].l == l && st[id].r == r)
{
st[id].add += add;
PushUp(id);
return;
}
if(st[id<<1].r >= r)
{
update(id<<1,l,r,add);
PushUp(id);
return;
}
if(st[id<<1|1].l <= l)
{
update(id<<1|1,l,r,add);
PushUp(id);
return;
}
update(id<<1,l,st[id<<1].r,add);
update(id<<1|1,st[id<<1|1].l,r,add);
PushUp(id);
}
int main()
{
//freopen("in.txt","r",stdin);
int t; scanf("%d",&t);
for(int cas = 1;cas <= t;cas++)
{
int n,m; scanf("%d%d",&n,&m);
Z[0] = 0;
for(int i = 1;i <= m;i++) scanf("%d",&Z[i]);
int k = 0;
for(int i = 1;i <= n;i++)
{
int x1,y1,x2,y2,z;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&z);
rec[i].x1 = x1;
rec[i].x2 = x2;
rec[i].y1 = y1;
rec[i].y2 = y2;
rec[i].z1 = 0;
rec[i].z2 = Z[z];
X[k++] = x1;
X[k++] = x2;
}//矩形读入完毕
sort(X,X+k);
buildtree(1,0,k-1);
sort(Z,Z+m+1);
LL ans = 0,lastarea = 0;
for(int i = 0;i <= m;i++)
{
if(i) ans += lastarea*LL(Z[i] - Z[i-1]);
int cnt = 0;
for(int j = 1;j <= n;j++)
{
if(rec[j].z1 <= Z[i] && rec[j].z2 > Z[i])
{
int u = lower_bound(X,X+k,rec[j].x1) - X;
int v = lower_bound(X,X+k,rec[j].x2) - X;
edge[cnt].x1 = u;
edge[cnt].x2 = v;
edge[cnt].y = rec[j].y1;
edge[cnt++].vis = 1;
edge[cnt].x1 = u;
edge[cnt].x2 = v;
edge[cnt].y = rec[j].y2;
edge[cnt++].vis = -1;
}
}
sort(edge,edge+cnt,cmp);
lastarea = 0;
LL lastlen = 0,lasty = 0;
for(int i = 0;i < cnt;i++)
{
if(i) lastarea += lastlen*LL(edge[i].y - lasty);
int u = edge[i].x1;
int v = edge[i].x2;
update(1,u,v,edge[i].vis);
lastlen = st[1].len;
lasty = edge[i].y;
}
}
printf("Case %d: %I64d\n",cas,ans);
}
return 0;
}
未完待续!欢迎路过的犇犇多多赐教