Codeforces Gym 100733J Summer Wars 线段树,区间更新,区间求最大值,离散化,区间求并
Summer Wars
Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88994#problem/J
Description
The mafia is finally resting after a year of hard work and not so much money. Mafianca, the little mascot of the gang wanted to go to the beach.
Little did they know that the rival gang had prepared a trap to the little girl and her rubber duck. They know that Mafianca, despite loving the beach, hates water. So they set up some water sprayers to ruin her day. The beach can be seen as a plane. The sprayers are located at different (x, y) points along the shore. Each sprayer is so strong that it creates an infinite line of water, reaching every point with x-coordinate equal to the sprayer.
Mafianca's bodyguards figured this plan out. They didn't have the time to destroy the sprayers, so they decided to do something else. Lying around on the beach was a piece of modern art: a bunch of walls, represented by horizontal line segments, painted by some futuristic anonymous artist. Those walls can be moved, but they can only be moved together and horizontally.
The bodyguards decided that they would try to move this piece of art in order to block the most sprayers they can. A sprayer is blocked if there's at least one wall in both of its sides.
How many sprayers can they block?
Input
Input begins with the number of sprayers, n (1 ≤ n ≤ 1000) and the number of walls in the modern art, m (1 ≤ m ≤ 1000).
Follows n lines, each with two intergers, y and x (0 ≤ y, x ≤ 106), indicating that there's a sprayer at position x, y.
Then follows m lines, each with three integers: y, xbegin and xend (0 ≤ y ≤ 106) and (0 ≤ xbegin < xend ≤ 106) denoting a wall in the modern art has y-coordinate y, begins at xbegin and ends at xend. No wall will have a y-coordinate shared with a sprayer and the walls with same y will not intersect.
Output
Print the number of sprayers that can be blocked.
Sample Input
1 1
2 2
3 1 3
Sample Output
0
HINT
题意
给你一些点,和一些平行于x轴的线段,然后你可以移动线段,但是你只能水平移动,并且必须一起移动所有线段
你需要挡住最多的点数
挡住点,要求这个点的上面至少有一个线段,下面也要有一个线段
题解:
我的做法比较繁琐……
先O(nm)求出每个线段要覆盖这个点需要平移多少,然后我们可以得到2m个区间,然后我们上下区间再求交集,然后再跑一遍线段树就好了……
想法比较简单,但是写起来感觉还是比较麻烦吧= =
我后面防止负数的区间,我还离散化了一发
代码:
//qscqesze #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 2000001 #define mod 10007 #define eps 1e-9 //const int inf=0x7fffffff; //无限大 const int inf=0x3f3f3f3f; /* */ //************************************************************************************** int n,q,a[100001]; struct data{ int l,r; long long mx; int tag; }tr[300001]; void build(int k,int s,int t) { tr[k].l=s;tr[k].r=t; if(s==t){tr[k].mx=a[s];return;} int mid=(s+t)>>1; build(k<<1,s,mid); build(k<<1|1,mid+1,t); tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx); } void pushdown(int k) { tr[k<<1].tag+=tr[k].tag; tr[k<<1|1].tag+=tr[k].tag; tr[k<<1].mx+=tr[k].tag; tr[k<<1|1].mx+=tr[k].tag; tr[k].tag=0; } void update(int k,int a,int b,int x) { int l=tr[k].l,r=tr[k].r; if(a==l&&r==b) { tr[k].tag+=x; tr[k].mx+=x; return; } if(tr[k].tag)pushdown(k); int mid=(l+r)>>1; if(b<=mid)update(k<<1,a,b,x); else if(a>mid)update(k<<1|1,a,b,x); else { update(k<<1,a,mid,x); update(k<<1|1,mid+1,b,x); } tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx); } long long ask(int k,int a,int b) { int l=tr[k].l,r=tr[k].r; if(a==l&&b==r){return tr[k].mx;} if(tr[k].tag)pushdown(k); int mid=(l+r)>>1; if(b<=mid)return ask(k<<1,a,b); else if(a>mid)return ask(k<<1|1,a,b); else return max(ask(k<<1,a,mid),ask(k<<1|1,mid+1,b)); } struct node { int x,y; }; node aa[1200]; struct line { int y,x1,x2; }; bool cmp(node aaa,node bbb) { if(aaa.x==bbb.x) return aaa.y<bbb.y; return aaa.x<bbb.x; } line bb[1200]; vector<node> Q1[1200]; vector<node> Q2[1200]; vector<node> T; map<int,int> H; vector<int> kkkk; vector<node> TT; int main() { int N,M; scanf("%d%d",&N,&M); for(int i=1;i<=N;i++) scanf("%d%d",&aa[i].y,&aa[i].x); for(int i=1;i<=M;i++) scanf("%d%d%d",&bb[i].y,&bb[i].x1,&bb[i].x2); for(int i=1;i<=N;i++) { for(int j=1;j<=M;j++) { if(aa[i].y>bb[j].y) Q1[i].push_back((node){aa[i].x-bb[j].x2,aa[i].x-bb[j].x1}); else Q2[i].push_back((node){aa[i].x-bb[j].x2,aa[i].x-bb[j].x1}); } } for(int i=1;i<=N;i++) sort(Q1[i].begin(),Q1[i].end(),cmp),sort(Q2[i].begin(),Q2[i].end(),cmp); for(int i=1;i<=N;i++) { int k=0; int tmp=-inf; TT.clear(); if(Q1[i].size()==0||Q2[i].size()==0) continue; int j=0; while(j<Q1[i].size()) { if(k>=Q2[i].size()) break; tmp = max(tmp,Q1[i][j].x); if(tmp>Q1[i][j].y) { j++; continue; } while(k<Q2[i].size()&&Q2[i][k].y<tmp) k++; if(k>=Q2[i].size()) break; int l = max(tmp,Q2[i][k].x); int r = min(Q1[i][j].y,Q2[i][k].y); if(Q1[i][j].y>Q2[i][k].y) k++; else j++; if(r<l) continue; tmp = max(l,r); TT.push_back((node){l,r}); } if(TT.size()==0) continue; sort(TT.begin(),TT.end(),cmp); int l=TT[0].x,r=TT[0].y; for(int j=1;j<TT.size();j++) { if(TT[j].x==r) r=TT[j].y; else { T.push_back((node){l,r}); l = TT[j].x; r = TT[j].y; } } T.push_back((node){l,r}); } for(int i=0;i<T.size();i++) kkkk.push_back(T[i].x),kkkk.push_back(T[i].y); sort(kkkk.begin(),kkkk.end()); kkkk.erase(unique(kkkk.begin(),kkkk.end()),kkkk.end()); for(int i=0;i<kkkk.size();i++) H[kkkk[i]]=i+1; build(1,1,kkkk.size()+1000); for(int i=0;i<T.size();i++) update(1,H[T[i].x],H[T[i].y],1); printf("%d\n",ask(1,1,kkkk.size()+500)); }