dtoi1363 building reconstruction (rebuild)

Meaning of the questions:

     There are n positions can build a house, at the beginning of each position are empty, every time you make the height of the house position x becomes y, from 0 to ask how many houses can be seen, x, y given . If any connection point of a height greater than 0 on the building for the (0,0) does not intersect the previous line, then This building is considered to be visible.

answer:

     If the highest point of the house and (0,0) the slope of the point of connection weights as each point, the answer is greedy rise of sub-length sequence. Greedy rising sequences is defined as: a start queue is empty, each time starting from 1, the tail encounters a large value than it is added to the tail put. (Rising sequence with the longest different)

     This problem can use tree line, but I do not know how to do, so I used a block.

     For each individual time seek a greedy rising sequence. Then, when seeking answers for each one, just put the last element in the current queue taken out, find the first location is larger than the element in the rise of the current block subsequence greedy, we can calculate the contribution of this piece of the . But need binary search efficiency is O (n * blocks * log (n)). (When I wrote here, I realized that half do not need, you can remove a log, but I'm too lazy changed). But this efficiency is really low, so take a few multi-block size can try several times before.

#include<cstdio>
#include<cmath> 
#include<algorithm>
#include<cstdlib>
using namespace std;
int n,m,fk,cnt,g[3002][3002],len[10000];
double h[100002];
int ccj(int num,int x,int y,int t){
    while(x<y)
    {
        int mid=(x+y)/2;
        if (h[g[num][mid]]/g[num][mid]>h[t]/t)y=mid;else x=mid+1;
    }
    return x;
}
int getans(){
    int x=1,ans=1;
    for (int i=0;i<=cnt;i++)
    {
        int wz=ccj(i,0,len[i],x),sum;
        sum=len[i]-wz;
        if (sum)
        {
            x=g[i][len[i]-1];ans+=sum;
        }
    }
    if (!h[1])ans--;
    return ans;
}
int main ()
{
    scanf("%d%d",&n,&m);
    fk=600;
    for (int i=1;i<=n;i++)
    {
        cnt=i/fk;
        if (!len[i/fk])g[i/fk][len[i/fk]++]=i;
    }
    for (int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        h[x]=y;len[x/fk]=0;int t=x/fk;
        for (int i=max(x/fk*fk,1);i<(x/fk+1)*fk&&i<=n;i++)
        if (!len[t] || h[i]/i>h[g[t][len[t]-1]]/g[t][len[t]-1])g[t][len[t]++]=i;
        printf("%d\n",getans());
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/1124828077ccj/p/12239337.html