Title Link: http://poj.org/problem?id=2528
Main idea of the title:
There are n posters to be posted on the wall. The starting position of each poster is given according to the posting order (only the abscissa is considered), and the number of posters that can be seen at last (as long as a little can be seen, it can be seen).
analysis:
1. Special discretization:
The discretization method here is to add any number if the distance between adjacent numbers is greater than 1, which is mainly to keep the originally non adjacent numbers non adjacent
This problem is to find out whether to expose the poster. After discretization, the poster that can be exposed before has a gap can not be leaked because it is closer. So in order to insert a value between two non adjacent numbers so that they do not become close.
give an example:
For example, the three posters are: 1 ~ 10 1 ~ 4 6 ~ 10
Discretize 1, 4, 6 and 10 to
1, 2 , 3 , 4
Therefore, 1 ~ 10 mark discretization 1, 2, 3 and 4 as serial number 1
1 ~ 4 mark discretization 1 and 2 as serial number 2, while 3 and 4 are still serial number 1
6 ~ 10 mark 3 and 4 as serial number 3, while 1 and 2 are still serial number 2
Then 1 and 2 after discretization are sequence number 2, while 3 and 4 are sequence number 3 So it seems that only two posters can be seen
In fact, you can see three posters, 1 ~ 4, 4 ~ 6, 6 ~ 10
This is mainly because the separated points are changed into continuous points in the process of discretization, so we need to add a value between each separated point for discretization.
For example, 1 4 6 10 becomes 1 2 4 5 6 7 10
The answer thus obtained is the qualified answer.
2. What does the segment tree maintain?
Since the interval given to us in this question is constantly modified by different posters, the segment tree maintains which poster is pasted in the current interval L~R. Moreover, since the corresponding Sn will be constantly modified, it is necessary to maintain the interval Sn by using the lazy flag
3. How to maintain:
You can use the push down method. When modifying, modify the lazy of the corresponding interval L~R to the corresponding serial number. When splitting is needed, the lazy flag of this interval is passed to the child nodes.
We can traverse the corresponding posters in sequence and use the modify() operation to constantly modify the value of the corresponding interval of the segment tree.
4. How to count how many posters can be seen in the end?
This query() function is different from the previous template. It directly traverses all nodes, looks for the lazy tags of all nodes in the corresponding segment tree, and counts the number of different lazy tags. These different lazy marks are the last total number of posters that can be seen.
5. Pay attention to the size of the tree structure of the opened line segment
Because each poster has two values X1 and X2, and at the same time, if it is discontinuous, new values will be added, up to twice the original value,
Therefore, the open size is N * 2 * 2 * 4.
Code implementation:
# include <iostream> # include <algorithm> # include <cstring> # include <vector> using namespace std; const int N = 10010; pair<int,int> p[N]; struct Node //The segment tree maintains a lazy tag { int l , r; int lazy; }edgs[N * 2 * 2 * 4]; // Each has two values y1,y2 Therefore, it is at least 2 * N * 4, plus the value added during discretization. In case each value is separated, it is doubled, so open N * 2 * 2 * 4 vector<int> a; //Discretization void pushdown(int u) { if(edgs[u].lazy != 0) { edgs[2 * u].lazy = edgs[u].lazy; edgs[2 * u + 1].lazy = edgs[u].lazy; edgs[u].lazy = 0; } } void build(int u , int l , int r) { edgs[u].l = l , edgs[u].r = r; edgs[u].lazy = 0; //Initialize as 0 without being overwritten by any posters if(l == r) { return; } else { int mid = (edgs[u].l + edgs[u].r ) / 2; build(2 * u , l , mid); build(2 * u + 1, mid + 1, r); } } void modify(int u , int l , int r , int c) // l. R is the modified interval, c is the serial number, which poster { if(l <= edgs[u].l && edgs[u].r <= r) { edgs[u].lazy = c; } else { pushdown(u); int mid = (edgs[u].l + edgs[u].r) / 2; if(l <= mid) { modify(2 * u , l , r , c); } if(r > mid) { modify(2 * u + 1, l , r , c); } } } int ans = 0; // answer bool flag[N]; //If you determine which color has been marked, you don't have to count it void query(int u , int l ,int r) { if(edgs[u].lazy!=0) { if(!flag[edgs[u].lazy]) { ans++; flag[edgs[u].lazy]=true; } } if(l >= r) //Make statistics of l~l, and then return, { return; } pushdown(u); int mid = (l +r) / 2; query(2 * u,l,mid); query(2 * u + 1 , mid + 1,r); } int find2(int x) // Binary find the index of the discretized value, and the index starts from 1 { int l = 1, r = a.size() - 1; while(l < r) { int mid = ( l + r ) / 2; if(a[mid] >= x) { r = mid; } else { l = mid + 1; } } return l; } int main() { int loop; scanf("%d",&loop); while(loop--) { ans = 0; memset(flag,false,sizeof flag); a.clear(); int n; scanf("%d",&n); for(int i = 1 ; i <= n ; i++) { int temp1,temp2; scanf("%d %d",&temp1,&temp2); p[i].first = temp1; p[i].second = temp2; a.push_back(temp1); a.push_back(temp2); } sort(a.begin(),a.end()); a.erase(unique(a.begin(),a.end()),a.end()); int temp = a.size(); // Because we'll insert a new value into a later and reorder it for(int i = 0 ; i < temp ; i++) { if(a[i] > a[i - 1] + 1) { a.push_back(a[i - 1] + 1); } } a.push_back(-0x3f3f3f3f); // I'm used to calculating subscripts from 1 sort(a.begin(),a.end()); //End of discretization build(1,1,a.size()); // Establish segment tree for(int i = 1 ; i <= n ; i ++) { int l = p[i].first; l = find2(l); int r = p[i].second; r = find2(r); modify(1,l,r,i); } query(1,1,a.size()); printf("%d\n",ans); } return 0; }