1. 程式人生 > >cogs 181. [USACO Jan07] 最高的牛

cogs 181. [USACO Jan07] 最高的牛

space 而且 pda () name limit nts info stdin

181. [USACO Jan07] 最高的牛

★★ 輸入文件:tallest.in 輸出文件:tallest.out 簡單對比
時間限制:1 s 內存限制:32 MB

FJ‘s N (1 ≤ N ≤ 10,000) cows conveniently indexed 1..N are standing in a line. Each cow has a positive integer height (which is a bit of secret). You are told only the height H (1 ≤ H ≤ 1,000,000) of the tallest cow along with the index I of that cow.

FJ has made a list of R (0 ≤ R ≤ 10,000) lines of the form "cow 17 sees cow 34". This means that cow 34 is at least as tall as cow 17, and that every cow between 17 and 34 has a height that is strictly smaller than that of cow 17.

For each cow from 1..N, determine its maximum possible height, such that all of the information given is still correct. It is guaranteed that it is possible to satisfy all the constraints.

為了方便我們把FJ養的N頭(1 ≤ N ≤ 10,000)奶牛從1號開始編號,一直編到N號,並且讓他們站成一列。每頭牛都有一個正整數用來描述她的身高(有些牛不願意說,她們的身高保密)。你只知道這些牛中最高的那一頭的身高是H,她的編號是第I號。

FJ寫了一張單子,上面有R個陳述句,大概是”第17號牛可以看見第34號牛”這種。這意味著第34號牛最起碼和第17號牛一樣高。而且17號牛和34號牛之間的牛得身高都嚴格的小於min(H[17],H[34])。

從第1號牛到第N號牛,求她們可能擁有的最大身高,所給出的所有信息都是正確的。這可以保證滿足所有條件。

Input

  • Line 1: Four space-separated integers: N, I, H and R
  • Lines 2..R + 1: Two distinct space-separated integers A and B (1 ≤ A, B ≤ N), indicating that cow A can see cow B.

輸入:

第1行:四個由空格分開的整數,N,I,H和R。

第2..R+1行:兩個由空格分開的整數A和B(1 ≤ A, B ≤ N),表示第A號牛可以看到第B號牛。

Output

  • Lines 1..N: Line i contains the maximum possible height of cow i.

輸出:

第1..N行:第i行包括第i號牛可能擁有的最大身高。

Sample Input

9 3 5 5
1 3
5 3
4 3
3 7
9 8

Sample Output

5
4
5
3
4
4
5
5
5

Input Details

There are 9 cows, and the 3rd is the tallest with height 5.

輸入細節:

由9頭奶牛,第三頭奶牛最高,身高是5.

譯byKZFFFFFFFF

思路:線段樹。

技術分享圖片
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 10000
using namespace std;
map<int,int>ma[MAXN];
struct nond{
    int l,r,flag;
}tree[MAXN*4];
long long n,I,H,R;
void build(int now,int l,int r){
    tree[now].l=l;tree[now].flag=0;
    tree[now].r=r;
    if(tree[now].l==tree[now].r)
        return ;
    long long mid=(tree[now].l+tree[now].r)/2;
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
}
void down(int now){
    tree[now*2].flag+=tree[now].flag;
    tree[now*2+1].flag+=tree[now].flag;
    tree[now].flag=0;
}
void change(int now,int l,int r){
    if(tree[now].l==l&&tree[now].r==r){
        tree[now].flag+=1;
        return ;
    }
    if(tree[now].flag)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    change(now*2,l,r);
    else if(l>mid)    change(now*2+1,l,r);
    else{
        change(now*2,l,mid);
        change(now*2+1,mid+1,r);
    }
}
int query(int now,int x){
    if(tree[now].l==tree[now].r)
        return tree[now].flag;
    if(tree[now].flag)    down(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(x<=mid)    return query(now*2,x);
    else if(x>mid)    return query(now*2+1,x);
}
int main(){
    //freopen("tallest.in","r",stdin);
    //freopen("tallest.out","w",stdout);
    while(scanf("%lld%lld%lld%lld",&n,&I,&H,&R)!=EOF){
        build(1,1,n);
        for(int i=1;i<=R;i++){
            long long a,b;
            scanf("%lld%lld",&a,&b);
            if(a>b)    swap(a,b);
            if(ma[a][b])    continue;
            ma[a][b]=1;
            if(a+1==b)    continue;
            change(1,a+1,b-1);
        }
        for(long long i=1;i<=n;i++)
            cout<<H-query(1,i)<<endl;
    }
}
一直調不對的20分代碼

AC代碼

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<algorithm>  
#include<limits.h>  
using namespace std;  
const int maxn=10000+100;  
int LL[maxn],RR[maxn];  
long long N,H,R,I;  
long long add[maxn<<2],ans[maxn];  
struct node{  
    int l,r;  
    int sum;  
}t[maxn<<2];  
void pushdown(int rs)//向下更新lazy積累的值  
{  
    if(add[rs])  
    {  
        add[rs<<1]+=add[rs];  
        add[rs<<1|1]+=add[rs];  
        add[rs]=0;  
    }  
}  
void build(int rs,int l,int r)  
{  
    t[rs].l=l;  
    t[rs].r=r;  
    add[rs]=0;  
    if(l==r)  
    { 
        t[rs].sum=H;  
        return ;  
    }  
    int mid=(l+r)>>1;  
    build(rs<<1,l,mid);  
    build(rs<<1|1,mid+1,r);  
}  
void update(int l,int r,int rs)//更新操作  
{  
    if(t[rs].l>=l&&t[rs].r<=r)  
    {  
        add[rs]+=1;  
        return ;  
    }  
    pushdown(rs);
    int mid=(t[rs].l+t[rs].r)>>1;  
    if(l<=mid)   update(l,r,rs<<1);  
    if(r>mid)  update(l,r,rs<<1|1);  
}  
int query(int k,int rs)  
{  
    if(t[rs].l==t[rs].r)  
    {  
        return t[rs].sum-=add[rs];  
    }  
    pushdown(rs);  
    int mid=(t[rs].l+t[rs].r)>>1;  
    if(k<=mid)  return query(k,rs<<1);  
    else  return query(k,rs<<1|1);  
}  
int main()  
{  
    freopen("tallest.in","r",stdin);
    freopen("tallest.out","w",stdout);
    int u,v;  
   scanf("%I64d%I64d%I64d%I64d",&N,&I,&H,&R);
        build(1,1,N);  
        int k=0;  
        while(R--)  
        {  
            scanf("%d%d",&u,&v);  
            if(u>v)  swap(u,v);  
            int flag=1;  
            for(int i=0;i<k;i++)//判斷重邊,在poj做題一定要防這東西  
            {  
                if(u==LL[i]&&v==RR[i])  
                {  
                    flag=0;  
                    break;  
                }  
            }  
            if(!flag)  
                continue;  
            LL[k]=u;RR[k]=v;  
            k++;  
            if(v-u==1)//相鄰的話就不用更新了  
                continue;  
  
            update(u+1,v-1,1);//註意是開區間的值更新  
        }  
        for(int i=1;i<=N;i++)  
            ans[i]=query(i,1);  
        for(int i=1;i<=N;i++)  
            printf("%I64d\n",ans[i]);  
    return 0;  
}  

cogs 181. [USACO Jan07] 最高的牛