2010年3月30日 星期二

TIOJ 1244 序列問題 Sequences [DP]

poao899    28K    4840MS    G++     0.36K     2010-03-31 02:50:18                                                    .






頗有趣的DP。




雷:





狀態存法   dp[n大小][該序列尾數]   但是這樣是10^8記憶體會爆炸

所以滾動。

另外是%100000007所以小心溢位。


轉移方式: dp[i-1][k]  + 結尾k or k+1    以及  開頭+1~k




//*******************************


#include<stdio.h>
#define MODE 100000007
int dp[10010], n, t;
long long tmp;
int main(){
    scanf("%d", &n);
    dp[1]= 1;
    for(int i=2; i<=n; i++){
        for(int j=i; j>0; j--){
            dp[j+1]+= dp[j];
            dp[j+1]%= MODE;
            tmp= (long long)dp[j]*j;
            dp[j]= (int)(tmp%MODE);
        }
    }
    for(int i=1; i<=n; i++){
        t+= dp[i];
        t%= MODE;
    }
    printf("%d\n", t);
}


POI - PA 2006 Crayfish (精神+翻譯)

沒co出來的有趣圖論                                                                                                    .


Round 4的題目好有趣但是好難orz




//*************************************

翻譯


給你一張有向圖,n<=10^4個頂點,m<=10^5條邊

有些邊是特殊的邊。

現在假設我拿i為起點,一開始只能逆的走(i.e.  a->b的邊只能從b走到a)

然後每經過一次特殊邊就得換方向(正走-> 逆走   反之亦然)

問你對於每個點的val值,val值定義為 從該點出發並要回到該點最多能經過多少其他的點



Input:
5 5
2 1 1
2 3 0
3 4 0
4 2 0
5 3 1


Output:


3
3
3
3
0


//***********************************


















雷:

把除了特殊的邊以外的正向圖及反向圖皆分別建出來,

每一條特殊的邊ex: a -> b


那麼就會從正向圖的a和反向圖的b做雙向邊


建完圖後SCC, 判重(同時走過一個點的正向跟反向)



















//************************************


POI - PA 2007 Encyclopedia [B]

30-03-10   11:10       Encyclopedia [B]      OK           10                                                           .


頗白癡的題目我說= =


說實話有點不值得Round 3的水準

就是給你一個由n個1    n個0組成的序列,每次交換相鄰兩個

問你把它轉成101010....   或010101....  最少要幾步










//***********************************

#include<stdio.h>
int in, n, pos, pos2;
long long ans, ans2;
long long abs(int a, int b){
if(a> b)return (long long)a-b;
return (long long)b-a;
}
int main(){
scanf("%d", &n);
pos= 1; pos2= 1;
for(int i=0; i<2*n; i++){
scanf("%d", &in);
if(in== 0){
ans+= abs(pos, i);
pos+= 2;
}else{
ans2+= abs(pos2, i);
pos2+= 2;
}
}
printf("%lld\n", ans<ans2? ans: ans2);
}


2010年3月29日 星期一

POI - PA 2008 Diagonals [B]

User: Chen Kuei-yi (poao899)
Date: 2010-03-30 03:44:39
Points 10
Comment: Algorithmic Engagements 2008, Round 3
Task: prz/Diagonals [B]
Date: 2010-03-30 05:04:08
Points: 10/10
Files: solution

Test case Status Time/Limit Points
 0   OK 0.00s/1.00s 0/0
 0a   OK 0.00s/1.00s 0/0
 1a   OK 0.00s/1.00s 1/1
 1b   OK 0.00s/1.00s
 2a   OK 0.00s/1.00s 1/1
 2b   OK 0.00s/1.00s
 3a   OK 0.00s/1.00s 1/1
 3b   OK 0.00s/1.00s
 3c   OK 0.00s/1.00s
 4a   OK 0.01s/1.00s 1/1
 4b   OK 0.00s/1.00s
 4c   OK 0.01s/1.00s
 5a   OK 0.01s/1.00s 1/1
 5b   OK 0.00s/1.00s
 5c   OK 0.00s/1.00s
 6a   OK 0.10s/1.00s 1/1
 6b   OK 0.00s/1.00s
 6c   OK 0.04s/1.00s
 7a   OK 0.31s/3.00s 1/1
 7b   OK 0.31s/3.00s
 8a   OK 0.09s/1.00s 1/1
 8b   OK 0.23s/3.00s
 9a   OK 1.06s/8.00s 1/1
 9b   OK 0.95s/8.00s
 9c   OK 5.40s/8.00s
 10a   OK 0.99s/8.00s 1/1
 10b   OK 0.90s/8.00s
 10c   OK 0.49s/8.00s
 10d   OK 5.61s/8.00s




不對啊AC沒道理啊  O(m lg m)sort +O(n)stack

m<=10^7, n<=10^6

怎麼看都不會AC的複雜度

還有拿掉gn跑得比較快ˊˋ


勝利得一點都不開心orz

對了,測資大概灌水兩倍

//*****************************************

#include<algorithm>
#define M 5000010
int n,m,q[M],r;
struct dia{
int i, j, o;
void get(int oo){
scanf("%d%d", &i, &j); o=oo;
if(i>j){i^=j^=i^=j;}
}
bool operator< (const dia &b)const{
return i<b.i || i==b.i&&j>b.j;
}
}d[M];
struct dia2{
int i, j, o;
void set(int ii, int jj, int oo){
i=ii; j=jj; o=oo;
}
bool operator< (const dia2 &b)const{
return j<b.j || j==b.j&&i>b.i;
}
}d2[M];
int main(){
scanf("%d%d", &n, &m);
if(m>M)m=M;
for(int i=0; i<m; i++){
d[i].get(i+1);
d2[i].set(d[i].i, d[i].j, i+1);
}
std::sort(d, d+m);
std::sort(d2, d2+m);
int di=0, di2=0;
for(int i=1; i<=n; i++){
for(; di2<m; di2++){
if(d2[di2].j==i){
if(q[r-1]== d2[di2].o){
r--;
}else{
printf("%d %d\n",q[r-1], d2[di2].o);
return 0;
}
}else break;
}
for(; di<m; di++){
if(d[di].i==i){
q[r]= d[di].o;
r++;
}else break;
}
}
puts("NIE");
}


TIOJ 1132 Dark Horse Escape [Greedy]

poao899    1776K    265MS    G++    0.66K     2010-03-29 19:08:07                                       .




反正擋他的位置一定不會比拐馬腳差...







//**********************************

#include<stdio.h>
#include<algorithm>
bool map[1011][1011];
struct horse{
int x, y;
bool operator<(const horse &b)const{
return x<b.x || x==b.x&&y<b.y;
}
void get(){
scanf("%d%d", &x, &y);
map[x][y]= 1;
}
}h[100010];
int n, cnt;
int main(){
while(~scanf("%d", &n)){
cnt= 0;
for(int i=0; i<1011; i++)
for(int j=0; j<1011; j++)
map[i][j]= 0;
for(int i=0; i<n; i++)
h[i].get();
std::sort(h, h+n);
for(int i=0; i<n; i++){
int x= h[i].x, y= h[i].y;
if(!map[x+1][y+2]&& !map[x][y+1])
{map[x+1][y+2]= 1; cnt++;}
if(!map[x+2][y+1]&& !map[x+1][y])
{map[x+2][y+1]= 1; cnt++;}
}
printf("%d\n", cnt);
}
}


2010年3月28日 星期日

TIOJ 1528 一字千金 [Tree]

poao899    4420K    6666MS    G++     2.34K     2010-03-29 13:51:35                          .

本篇全部都是雷(?





































阿思:就把他想成一棵樹多了8條邊,然後去枚舉就好了

說實話也不好枚舉orz

一開始很直覺的2^8= 256的枚舉

可以想一下以下這組測資

3 3
10 100 10
1 2
2 3
1 3

答案應該是100

但是3^8= 6561太大了會TLE



而且還有一組測資

3 4
10 10 10
1 2
2 3
3 1
1 2

答案絕對是10

然後下面那組真的是我自己的問題了orz

8 9
6 3 5 2 5 3 1 4
1 2
2 4
4 5
6 4
4 8
5 7
3 5
2 6
7 8

答案是18



所以就變成2^8 *(O(e)檢查 + O(v)DP)

//*******************************

#include<stdio.h>
long long dp[50100][2], max;
int deter[50100], speCnt, n, m, val[50100], a, b, ra, rb;
int root[50100], fa[50100];
int find(int a){return root[a]==a? a: root[a]=find(root[a]);}
//0= no  1= 一定要  2= 一定不能
struct edge{
    int i, j;
    edge *next;
}e[100100], spe[10], *p, *v[50100];
void dfs(int n){
    bool can= 1;
    dp[n][0]= dp[n][1]= 0;
    for(edge *ptr=v[n]; ptr; ptr=ptr->next){
        if(fa[n]== ptr->j)continue;
        fa[ptr->j]= n;
        dfs(ptr->j);
        if(deter[ptr->j]== 1)
            can= 0;
    }
    if(deter[n]!= 2&& can){
        dp[n][1]= val[n];
        for(edge *ptr=v[n]; ptr; ptr=ptr->next){
            if(fa[n]== ptr->j)continue;
            dp[n][1]+= dp[ptr->j][0];
        }
    }if(deter[n]!=1){
        for(edge *ptr=v[n]; ptr; ptr=ptr->next){
            if(fa[n]== ptr->j)continue;
            if(deter[ptr->j]==2)
                dp[n][0]+= dp[ptr->j][0];
            else if(deter[ptr->j]==1)
                dp[n][0]+= dp[ptr->j][1];
            else dp[n][0]+= dp[ptr->j][0]>dp[ptr->j][1]? dp[ptr->j][0]: dp[ptr->j][1];
        }
    }
}
int main(){
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++){
        root[i]= i;
        scanf("%d", val+i);
    }
    for(int i=0; i<m; i++){
        scanf("%d%d", &a, &b);
        ra= find(a);
        rb= find(b);
        if(ra==rb){
            spe[speCnt].i=a; spe[speCnt].j=b;
            speCnt++;
        }else{
            e[i].i=a; e[i].j=b;
            p=v[a]; v[a]=&e[i]; e[i].next=p;
            e[i+m].i=b; e[i+m].j=a;
            p=v[b]; v[b]=&e[i+m]; e[i+m].next=p;
            root[rb]= ra;
        }
    }
   
    int ii= 1<<speCnt;
    for(int i=0; i<ii; i++){
        //init
        bool can= 1;
        for(int j=1; j<=n; j++)
            fa[j]=j;
        for(int j=0; can&& j<speCnt; j++){
            if(i& (1<<j)){
                deter[spe[j].i]= 2;
                deter[spe[j].j]= 0;
            }else{
                deter[spe[j].i]= 1;
                deter[spe[j].j]= 2;
            }
        }
        for(int i=0; can&& i<m; i++)
            if(deter[e[i].i]== 1&& deter[e[i].j]== 1)
                can=0;
        for(int i=0; can&& i<speCnt; i++)
            if(deter[spe[i].i]== 1&& deter[spe[i].j]== 1)
                can=0;
        if(!can)continue;
        dfs(root[1]);
        for(int j=0; j<2; j++)
            if(dp[root[1]][j]> max)
                max=dp[root[1]][j];
    }

    printf("%I64d\n",max);
}


TIOJ 1325 倍因道 - EXTREME

    poao899    1948K    326MS    G++     0.89K     2010-03-29 00:10:54                                    .



我說code風格好醜= =


然後用1241來Debug...不行   思路不夠清楚






O(n ln n)+ T*O(1)


//**************************

#include<stdio.h>
#include<algorithm>
#define MAX 100000
struct stuff{
    int ori, cmp;
    bool operator<(const stuff &b)const{
        return cmp<b.cmp;
    }
}s[100010];
int sieve[100010], dp[100010], get[100010], t, n;
int main(){
   
    for(int i=1; i<=MAX; i++)
        for(int j=i+i; j<=MAX; j+=i)
            sieve[j]++;

    for(int i=1; i<=MAX; i++){
        s[i-1].ori= i;
        s[i-1].cmp= (sieve[i]+1)* i;
    }
    std::sort(s, s+MAX);
    for(int i=1,j=0; i<=MAX; i++){
        dp[i]= dp[i-1];
        while(j<MAX&& s[j].cmp<=i){
            dp[i]-= sieve[s[j].ori];
            for(int z=s[j].ori*2; z<=MAX; z+=s[j].ori){
                if(z<i)dp[i]++;
                get[z]++;
            }
            j++;
        }
        dp[i]+= get[i];
    }
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        printf("%d\n", dp[n]);
    }
}


TIOJ 1130 Dark Kingdom II [Greedy]

poao899    228K    546MS    G++     0.81K     2010-03-28 15:22:42                            .

奇怪最近寫一大堆Greedy


是說我無法證明這是正確的耶zzz

只是覺得超合理   寫起來超毛的











而且看著大家的code length 好像只有我有co     Heap          耶Q

//**************************

#include<algorithm>
int n, m, st[30000], ed[30000], c1, c2, top;
int main(){
    while(~scanf("%d%d",&n,&m)){
        c1=c2=0; top=m;
        for(int i=0; i<m; i++){
            scanf("%d%d", st+i, ed+i);
            c1+= (st[i]>ed[i]? ed[i]+n-st[i]: ed[i]-st[i]);
        }
        std::sort(st, st+m);
        for(int i=0; i<m; i++){
            if(ed[i]< st[0])
                ed[i]+= n;
            ed[i]= -ed[i];
        }
        std::make_heap(ed, ed+top);
        for(int i=0; i<m; i++){
            while(-ed[0]< st[i]){
                std::pop_heap(ed, ed+top--);
                ed[top]-= n;
                std::push_heap(ed, ed+top++);
            }
            c2+= -ed[0]-st[i];
            std::pop_heap(ed, ed+top--);
        }
        printf("%d\n", c1-c2);
    }
}


2010年3月27日 星期六

TIOJ 1133 Dark Teleport Field [Brute Force]

    poao899    108K    15MS    G++     2.44K     2010-03-28 14:23:25                             .


Debug超超超久orz


原來是兩個矩形的距離算錯

這題只是很暴力不難才對啊orzzzzzzzzzzzzzz








//*************************

#include<stdio.h>
#define QLEN 2000
#define MAXV 160
#define MAXK 10
int d[MAXV][MAXV],dist[MAXV][MAXK];
struct rec{
    int x1,y1,x2,y2;
    void get(){
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    }
    int dist(int x,int y){
        int d=0;
        if(x<x1||x>x2)x<x1? d+=x1-x: d+=x-x2;
        if(y<y1||y>y2)y<y1? d+=y1-y: d+=y-y2;
        return d;
    }
}r[200];
//0 st  1~m rec  m+1 ed
int q[QLEN][2],front,rear,n,m,t,k,sx,sy,ex,ey;
bool inq[MAXV][MAXK];
int main(){
    while(~scanf("%d%d",&n,&m)){
        for(int i=1; i<=m; i++)
            r[i].get();
        for(int i=1; i<=m; i++)
            for(int j=1; j<=m; j++){
                d[i][j]= 2147483647;
                if(d[i][j]> r[i].dist(r[j].x1, r[j].y1))
                    d[i][j]= r[i].dist(r[j].x1, r[j].y1);
                if(d[i][j]> r[i].dist(r[j].x2, r[j].y1))
                    d[i][j]= r[i].dist(r[j].x2, r[j].y1);
                if(d[i][j]> r[i].dist(r[j].x2, r[j].y2))
                    d[i][j]= r[i].dist(r[j].x2, r[j].y2);
                if(d[i][j]> r[i].dist(r[j].x1, r[j].y2))
                    d[i][j]= r[i].dist(r[j].x1, r[j].y2);
                   
                if(d[i][j]> r[j].dist(r[i].x1, r[i].y1))
                    d[i][j]= r[j].dist(r[i].x1, r[i].y1);
                if(d[i][j]> r[j].dist(r[i].x2, r[i].y1))
                    d[i][j]= r[j].dist(r[i].x2, r[i].y1);
                if(d[i][j]> r[j].dist(r[i].x2, r[i].y2))
                    d[i][j]= r[j].dist(r[i].x2, r[i].y2);
                if(d[i][j]> r[j].dist(r[i].x1, r[i].y2))
                    d[i][j]= r[j].dist(r[i].x1, r[i].y2);
            }
        scanf("%d",&t);
        while(t-->0){
            scanf("%d%d%d%d%d",&k,&sx,&sy,&ex,&ey);
            //init
            front=0; rear=1;
            for(int i=0;i<MAXV;i++){
                for(int j=0;j<MAXK;j++){
                    inq[i][j]=0;
                    dist[i][j]=1000000000;
                }
            }
            for(int i=1;i<=m;i++){
                d[i][0]=d[0][i]=r[i].dist(sx,sy);
                d[i][m+1]=d[m+1][i]=r[i].dist(ex,ey);
            }
            d[0][m+1]= d[m+1][0]= (sx>ex? sx-ex: ex-sx)+ (sy>ey? sy-ey: ey-sy);
            q[front][0]= q[front][1]= dist[0][0]= 0; inq[0][0]= 1;
            while(front!=rear){
                int now=q[front][0], dep=q[front][1];
                if(dep<=k){
                    for(int i=1; i<=m; i++){
                        if(dist[i][dep+1]> dist[now][dep]+d[now][i]){
                            dist[i][dep+1]= dist[now][dep]+d[now][i];
                            if(!inq[i][dep+1]){
                                q[rear][0]=i;
                                q[rear][1]=dep+1;
                                inq[i][dep+1]=1;
                                rear=++rear%QLEN;
                            }
                        }
                    }
                    if(dist[m+1][dep]> dist[now][dep]+d[now][m+1])
                        dist[m+1][dep]= dist[now][dep]+d[now][m+1];
                    inq[now][dep]=0;
                }
                front=++front%QLEN;
            }
            int min=2147483647;
            for(int i=0;i<=k;i++)
                if(min> dist[m+1][i])
                    min= dist[m+1][i];
            printf("%d\n",min);
        }
    }
}


TIOJ 1440 誰買早餐 [Greedy]

    poao899    23496K    7525MS    G++     0.56K     2010-03-28 12:53:38                              .


空虛題竟然沒有一次AC= =

第一次沒判斷Impossible

第二次沒處理每項早餐只有一個...


營養越高價錢越高



沒這個條件就不知道怎麼做了XD

















//**********************************
#include<stdio.h>
#include<algorithm>
long long p[1000010],cost;
int n, m;
struct bf{
long long b,c;
void get(){
scanf("%I64d%I64d",&b,&c);
}
bool operator<(const bf &z)const{
return b< z.b;
}
}b[1000010];
int main(){
scanf("%d", &n);
for(int i=0; i<n; i++)
scanf("%I64d", p+i);
std::sort(p, p+n);
scanf("%d", &m);
for(int i=0; i<m; i++)
b[i].get();
std::sort(b, b+m);
for(int i=0,j=0; i<n ;i++){
for(; b[j].b<p[i]&&j<m; j++);
if(j==m){puts("Impossible."); return 0;}
cost+= b[j++].c;
}
printf("%I64d\n", cost);
}



TIOJ 1406 魚 FISH [Greedy]

    poao899    1556K    545MS    G++     0.68K     2010-03-28 12:31:29                                     .


奇怪為什麼之前想這麼久

明明沒有很難ˇ    頗可愛的題目>//<

















//*****************************

#include<stdio.h>
long long p[100010], f[100010], mid, l, r;
int n;
long long getl(){
long long g=0;int c=getchar();
while(c==10||c==32||c==9)c=getchar();
while(c>='0'&&c<='9'){
g=g*10+c-48;
c=getchar();
}
return g;
}
bool test(){
long long rest=0;
f[0]=mid;
for(int i=1; i<=n; i++){
if(rest)rest-= p[i]-p[i-1];
rest+= f[i]-mid;
}
return rest>=0;
}
int main(){
while(~scanf("%d", &n)){
l=9223372036854775807LL; r=-9223372036854775807LL;
for(int i=1; i<=n; i++){
p[i]=getl(); f[i]=getl();
if(f[i]>r)r=f[i];
if(f[i]<l)l=f[i];
}
while(l!=r){
mid=(l+r+1)/2;
if(test())l=mid;
else r=mid-1;
}
printf("%I64d\n",l);
}
}



TIOJ 1410 Comiket [sort]

poao899    15652K    890MS    G++     0.63K     2010-03-27 20:58:10                                  .


不想說什麼了orz


只是在寫水題而已...



//************************

#include<stdio.h>
#include<algorithm>
int n,nowp,maxp,t;
int getint(){
int g=0,c=getchar();
while(c==10||c==32||c==9)c=getchar();
if(c==EOF)return -1;
while(c>='0'&&c<='9'){
g=g*10+c-48;
c=getchar();
}
return g;
}
struct peo{
int t,in;
bool operator<(const peo &b)const{
return t<b.t || t==b.t&&in>b.in;
}
}p[2000010];
int main(){
while(~(n=getint())){
nowp=maxp=t=0;
for(int i=0;i<n;i++){
p[t].t=getint();
p[t++].in=1;
p[t].t=getint();
p[t++].in=-1;
}
std::sort(p,p+t);
for(int i=0;i<t;i++){
nowp+=p[i].in;
if(nowp>maxp)maxp=nowp;
}
printf("%d\n",maxp);
}
}


TIOJ 1311 好多星星ver 1.5

nolonger    -8K    30MS    G++     0.29K     2010-03-27 19:09:32                              .

好糟糕的題目orz

難怪一堆人吃OLE

一次AC的好像只有球主 akira 姜姜跟小乃...


























所有數字<=2^31-1

所以用for(int i=x1 ; i<x2 ; i++)在x1=x2=2^31-1就爆炸了...


//****************************

#include<algorithm>
int z,x1,x2,y1,y2,t;
int main(){
    while(~scanf("%d",&z)&&z){
        scanf("%d%d%d%d",&x1,&x2,&y1,&y2);
        for(int i=y1; i>0&&i<=y2; i++){
            t=std::__gcd(z,i);
            for(int j=x1; j>0&&j<=x2; j++)
                putchar(std::__gcd(t,j)>1? '.': '*');
            puts("");
        }puts("--");
    }
}


TIOJ 1550 鏡框設置回來了!

 poao899    72K    2246MS    G++     0.63K     2010-03-27 18:24:24                                       .


第一個複雜度很好想但是一定會TLE= =





















O(nm lg m) -> O(nm)


//***************************

先counting一下,然後檢查每個(上次有出現的數字+1)這次有沒有出現

//***************************

#include <stdio.h>
int dp[1600],n,m,t,max,count[16000];
int l1[1600],l2[1600],top,otop,cnt;
int main(){
int *old=l1,*list=l2,*tmp;
scanf("%d%d\n",&n,&m);
for(int i=0; i
top=cnt=0;
for(int j=0; j
count[old[j]]=0;
for(int j=0; j
getchar()=='1'? dp[j]++: dp[j]=0;
count[dp[j]]++;
}
getchar();
if(count[1])list[top++]=1;
for(int j=0; j
if(count[ old[j]+1 ])
list[top++]= old[j]+1;
for(int j=top-1;j>=0;j--){
cnt+=count[ list[j] ];
t=cnt*list[j];
if(t>max)max=t;
}
tmp=old; old=list; list=tmp; otop=top;
}
printf("%d\n",max);
}


TIOJ 1226 H遊戲 [Graph]

poao899    3772K    312MS    G++     1.07K     2010-03-27 17:05:15                                        .




題目是說   給一張DAG,問你從A到B所有走法的路徑和%32768

V<=1000, E<=10^6

































就topological sort + DP



//*********************************

#include<stdio.h>
#define MODE 32768
char name[100][25];
int stamp[1010],ttime,cost[1010],dp[1010],t,n,v,e,x,y,z;
bool visited[1010];
struct edge{
    int j,cost;
    edge *next;
}E[1000010],*V[1010];
void dfs(int n){
    visited[n]=1;
    for(edge *p=V[n]; p; p=p->next)
        if(!visited[p->j])
            dfs(p->j);
    stamp[ttime++]=n;
}
int main(){
    scanf("%d\n",&t);
    for(int cnt=1;cnt<=t;cnt++){
        printf("Game #%d\n",cnt);
        //init
        scanf("%d%d%d\n",&n,&v,&e);
        for(int i=0;i<v;i++){
            cost[i]=dp[i]=visited[i]=stamp[i]=0;
            V[i]=NULL;
        }
        dp[0]=1;
        ttime=0;
        //input
        for(int i=0;i<n;i++)
            gets(name[i]);
        for(int i=0;i<e;i++){
            //printf("i=%d e=%d\n",i,e);
            scanf("%d%d%d",&x,&y,&z);
            edge *p=&E[i],*q=V[x];
            V[x]=p; p->j=y; p->next=q; p->cost=z;
        }
        //time stamp
        dfs(0);
        //dp
        for(int i=ttime-1;i>=0;i--){
            int now=stamp[i];
            for(edge *p=V[now]; p; p=p->next){
                cost[p->j]+=cost[now]+ p->cost*dp[now];
                cost[p->j]%=MODE;
                dp[p->j]+=dp[now];
            }
        }
        for(int i=0;i<n;i++)
            printf("%s: %d\n",name[i],cost[i+1]);
    }
}


TIOJ 1237 砍了那些腳 Cut Many Legs [Greedy]

poao899    15648K    2009MS    G++     0.76K     2010-03-27 15:44:35                                .

同UVa 10291不過測資加大(50 →  2*10^6)


是說這題題目頗難懂Q

以下是解釋小心雷

//***************************************

一個桌子會傾斜,就是因為把兩個平衡又高的腳連線當支點,

其中有一邊全部都是短腳而且佔其他所有桌腳重量一半( >= floor( (n-1)/2 ) )

Ex 1:

7
3 3 1 1 3 1 1
平衡 所以0

Ex 2:

6
3 1 1 3 3 3
不平衡所以全部砍到剩下1,答案是8

也就是找到一個數字是k,讓數列不能有連續(n-1)/2個數字小於k

//***************************************

#include<stdio.h>
int leg[4000010],n;
int l,r,mid,limit;
long long cut;
bool test(){
    int s=0;
    for(int i=0;i<n*2;i++){
        s++;
        if(leg[i]>mid)s=0;
        if(s>=limit)return 0;
    }
    return 1;
}
int getint(){
    int g=0,c=getchar(),s=1;
    while(c==32||c==10||c==9)c=getchar();
    if(c=='-'){s=-1;c=getchar();}
    while(c>='0'&&c<='9'){
        g=g*10+c-48;
        c=getchar();
    }
    return g*s;
}
int main(){
    while(n=getint()){
        l=2147483647;r=-214748364;cut=0;
        limit=(n-1)/2;
        for(int i=0;i<n;i++){
            leg[i+n]=leg[i]=getint();
            if(leg[i]>r)r=leg[i];
            if(leg[i]<l)l=leg[i];
        }
        while(l!=r){
            mid=(l+r)/2;
            if(test())l=mid+1;
            else r=mid;
        }
        for(int i=0;i<n;i++)
            if(leg[i]>l)cut+=leg[i]-l;
        printf("%lld\n",cut);
    }
}




TIOJ 1529 邪惡的魔人姜姜 [Greedy]

poao899    15676K    6995MS    G++     1.37K     2010-03-27 13:12:37                                  .




說Greedy應該沒有捏到人吧(小聲

是說讓我爆炸的測資是

2
3.0 5.0
4.0 7.0

我會輸出50.000   應該很明顯問題在哪裡吧XDD

正確輸出是0.000



反正就是維持一個Heap

不過還是不習慣用STL...

小心浮點數誤差(?


//**************************************

#include<stdio.h>
#include<algorithm>
int n,top,allpow;
double pre_t,tored;
double hp;
int inline cmp(double a,double b){
    double d=a-b;
    if(d>10e-7)return -1;
    else if(d<-10e-7)return 1;
    return 0;
}
double min(double a,double b){
    if(cmp(a,b)==1)return a;
    return b;
}
struct loli{
    double w,t;
    bool operator<(const loli &b)const{
        return cmp(t,b.t)==1 || !cmp(t,b.t)&&cmp(w,b.w)==-1;
    }
    void get(){
        scanf("%lf%lf",&w,&t);
    }
}l[500020];
struct ele{
    double w,red;
    bool operator<(const ele &b)const{
        return cmp(w,b.w)==1;
    }
}heap[500020];
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        l[i].get();
    std::sort(l,l+n);
    for(int i=0;i<n;i++){
        heap[top].w=l[i].w;
        heap[top++].red=0;
        std::push_heap(heap,heap+top);
        tored=pre_t+l[i].w-l[i].t;
        if(cmp(tored,0.0)==1)tored=0;
        while(cmp(tored,0.0)==-1){
            if(cmp(heap[0].w-heap[0].red , tored)==-1){
                heap[0].red+=tored;
                tored=0;
            }else{
                allpow++;
                tored-=(heap[0].w-heap[0].red);
                heap[0].red=heap[0].w=0;
                std::pop_heap(heap,heap+top);top--;
            }
        }
        pre_t = min( l[i].t , pre_t+l[i].w );
    }
    for(int i=0;i<top;i++)
        if(cmp(heap[i].red,0)==-1)
            hp+=heap[i].red*100/heap[i].w;
    printf("%.3lf\n",hp+100.0*allpow);
   
}


2010年3月24日 星期三

TIOJ 1445 機器人組裝大賽 [次小生成樹]

poao899    13860K    1730MS    G++     1.90K     2010-03-24 19:14:56                                        .


次小生成樹。

利 用k小生成樹定理

變成 V^2(有點類似RMQ的東東) + E*O(1)(查詢)


               long long              表= =



//*********************************

#include<cstdio>
#include<algorithm>
#define MAXV 1010
#define MAXE 500000

long long mst,mst2;
int n,m;
//gn
int getint(){
    int g=0,c=getchar(),s=1;
    while(c==10||c==32||c==9)c=getchar();
    if(c=='-'){s=-1;c=getchar();}
    while(c>='0'&&c<='9'){
        g=g*10+c-48;
        c=getchar();
    }
    return g*s;
}
long long get64(){
    long long g=0;int c=getchar(),s=1;
    while(c==10||c==32||c==9)c=getchar();
    if(c=='-'){s=-1;c=getchar();}
    while(c>='0'&&c<='9'){
        g=g*10+c-48;
        c=getchar();
    }
    return g*s;
}
//kruskal's necessity
struct ways{
    int i,j;
    long long c;
    bool used;
    void get(){
        i=getint();j=getint();c=get64();
    }
    bool operator<(const ways &b)const{
        return c<b.c;
    }
}w[MAXE];
int root[MAXV];
int find(int a){
    return root[a]==a?a:root[a]=find(root[a]);
}
int uni(int a,int b){
    int ra=find(a),rb=find(b);
    root[ra]=rb;
}
//DFS' necessity
struct edge{
    int j;
    long long c;
    edge *next;
}e[MAXE],*v[MAXV];
void push(int i,int j,int c){
    static int cnt=0;
    edge *p=e+cnt++,*q;
    p->j=j;p->c=c;
    q=v[i];
    v[i]=p;
    p->next=q;
}
bool visited[MAXE],dfsed[MAXE];
long long dp[MAXV][MAXV];
int now;
void dfs(int n){
    edge *p=v[n];
    visited[n]=1;
    for(;p!=NULL;p=p->next)
        if(!visited[p->j]){
            dp[now][p->j]=dp[now][n]>p->c ? dp[now][n] : p->c;
            dfs(p->j);
        }
}
int main(){
    //input
    n=getint();m=getint();
    for(int i=0;i<m;i++)
        w[i].get();
    //kruskal
    std::sort(w,w+m);
    int edgeAdded=0;
    for(int i=0;i<=n;i++)root[i]=i;
    for(int i=0;i<m && edgeAdded<n-1;i++){
        if(find(w[i].i)!=find(w[i].j)){
            uni(w[i].i , w[i].j);
            edgeAdded++;
            mst+=w[i].c;
            //build gragh
            push(w[i].i,w[i].j,w[i].c);
            push(w[i].j,w[i].i,w[i].c);
            w[i].used=1;
        }
    }
        //if can't find MST
    if(edgeAdded!=n-1){puts("-1 -1");return 0;}
    printf("%I64d ",mst);
    //DFS, to find MST2
    mst2=9223372036854775807LL;
    for(int z=0;z<m;z++){
        if(w[z].used)continue;
        int x=w[z].i,y=w[z].j;
        if(dfsed[x])
            mst2=mst2<w[z].c-dp[x][y]?mst2:w[z].c-dp[x][y];
        else if(dfsed[y])
            mst2=mst2<w[z].c-dp[y][x]?mst2:w[z].c-dp[y][x];
        else{
            //init
            for(int i=0;i<MAXV;i++)
                visited[i]=0;
            now=x;dfsed[x]=1;
            dfs(x);
            mst2=mst2<w[z].c-dp[x][y]?mst2:w[z].c-dp[x][y];
        }
    }
    if(mst2==9223372036854775807LL)puts("-1");
    else printf("%I64d\n",mst+mst2);
}

2010年3月8日 星期一

TIOJ 1575 欸西國的欸西M大賽(Accepted) [97校內 prob6]

 poao899    36288K    16822MS    G++     1.68K     2010-03-08 17:25:08                                                   .



題意是這樣的,給你一棵樹,n<10^6,選出k個點(k<10^6),

請問對於每個樹上的點,要走到這k個點的最短距離的最大值是多少?













Hint:





對答案二分搜,

再從樹葉Greedy

噢對了記得要寫stack



//****************************************

#include<stdio.h>
#define MAXN 2000100
struct edge{
    int j;
    edge *next;
}*v[MAXN],e[MAXN*2],*ptr,*nowe;
void set(int i,int j){
    static int cnt=0;
    nowe=&e[cnt++];
    ptr=v[i];
    v[i]=nowe;
    nowe->j=j;
    nowe->next=ptr;
}
int ar[MAXN],top;
int dp[MAXN],dmax,dnow;
int max[MAXN],min[MAXN],fa[MAXN];
int n,m,k,a,b;
bool can,visited[MAXN];
bool chk(){
    can=1;dnow=0;
    for(int i=0;i<=n;i++)
        visited[i]=0;
    ar[1]=top=1;
    while(top){
        int now=ar[top];
        if(!can)return 0;
        if(now>0){
            max[now]=-1;min[now]=0;
            visited[now]=1;
            dp[now]=0;
            ar[top]=-now;
            int max=-1,min=0;
            for(edge *ptr=v[now];ptr;ptr=ptr->next){
                if(visited[ptr->j]){
                    fa[now]=ptr->j;
                    continue;
                }
                ar[++top]=ptr->j;
            }
        }else{
            now=-now;
            if(max[now]>=dmax-1){
                dp[now]=-dmax;
                dnow++;
                if(dnow>k)
                    can=0;
            }
            else if(max[now]<0){
                if(min[now]<0)
                    dp[now]=min[now]+1;
            }
            else{
                if(-min[now]-2>=max[now])
                    dp[now]=min[now]+1;
                else
                    dp[now]=max[now]+1;
            }
            if(dp[now]>max[fa[now]])
                max[fa[now]]=dp[now];
            if(dp[now]<min[fa[now]])
                min[fa[now]]=dp[now];
            top--;
        }
    }
    if(dp[1]>0)dnow++;
    return can&&dnow<=k;
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    if(n==k){puts("0");return 0;}
    else if(k==0){printf("%d\n",n-1);return 0;}
    if(n-1!=m)for(;;)puts("XDD");
    for(int i=0;i<m;i++){
        scanf("%d%d",&a,&b);
        set(a,b);
        set(b,a);
    }
    int _l=0,_r=n;
    while(_l!=_r){
        dmax=(_l+_r)/2;
        if(!chk())
            _l=dmax+1;
        else _r=dmax;
    }
    printf("%d\n",_l);
}


2010年3月4日 星期四

TIOJ 1202 重疊的天際線

 nolonger    1104K    249MS    G++    1.79K     2010-03-04 21:14:24                                     .


蝴蝶的1k一定是因為另有正解!


怪噁心的Heap= =


#include<stdio.h>
#include<algorithm>
#define MAX 30010
int n,pos,ary[MAX*2],cnt,np,bcnt;
bool fl;
struct skyline{
    int hei[MAX],pos[MAX],rear;
    void init(){
        rear=hei[0]=0;
        pos[0]=1;
    }
    void push(int x,int y){
        if(pos[rear]==x){
            if(hei[rear]<y)
                hei[rear]=y;
        }
        else if(hei[rear]!=y){
            hei[++rear]=y;
            pos[rear]=x;
        }
    }
}s;
struct ele{
    int l,r,h;
    bool operator<(const ele &b)const{
        return h<b.h;
    }
    inline void get(){
        scanf("%d%d%d",&l,&h,&r);
        ary[cnt++]=l;
        ary[cnt++]=r;
    }
}e[MAX];
bool cmp(ele a,ele b){
    return a.l<b.l;
}
struct heap{
    ele ar[MAX],t;
    int rear;
    void ch(int a,int b){
        t=ar[a];
        ar[a]=ar[b];
        ar[b]=t;
    }
    void upset(int n){
        if(n<2||n>=rear)return;
        int t=n/2;
        if(ar[t]<ar[n]){
            ch(t,n);
            upset(t);
        }
    }
    void downset(int n){
        if(n<1||n>=rear)return;
        int t=n<<1,opt;
        if(t<rear&&ar[n]<ar[t]){
            opt=t+1<rear&&ar[t]<ar[t+1];
            ch(t+opt,n);
            downset(t+opt);
        }
        else if(t+1<rear&&ar[n]<ar[t+1]){
            ch(t+1,n);
            downset(t+1);
        }
    }
    void push(ele a){
        ar[rear]=a;
        upset(rear++);
    }
    void pop(){
        if(rear<2)return;
        ch(1,--rear);
        downset(1);
    }
}h;
int main(){
    while(scanf("%d",&n),n){
        s.init();
        h.rear=1;
        bcnt=cnt=np=fl=0;
        for(int i=0;i<n;i++)
            e[i].get();
        std::sort(e,e+n,cmp);
        std::sort(ary,ary+cnt);
        e[n].l=0;e[n].r=ary[cnt-1]+1;e[n].h=0;
        h.push(e[n]);
        for(int i=0;i<cnt;){
            pos=ary[i];
            for(;bcnt<n&&e[bcnt].l<=pos;bcnt++)
                h.push(e[bcnt]);
            while(h.ar[1].r<=pos)
                h.pop();
            s.push(pos,h.ar[1].h);
            while(i<cnt&&ary[i]==pos)i++;
        }
        for(int i=0;i<=s.rear;i++){
            if(s.pos[i]==1&&s.hei[i]==0)continue;
            if(fl)putchar(32);
            printf("%d %d",s.pos[i],s.hei[i]);
            fl=1;
        }
        putchar('\n');
    }
}


TIOJ 1231 寵物雞問題 (TOI 2005) [Greedy]

  poao899    1168K    325MS    G++     1.13K     2010-03-04 18:16:59                                             .



Greedy.

是說竟然寫出了O(n)的Heap= =



#include<stdio.h>
#include<algorithm>
#define MAX 100010
int n,ed,weight,cnt;
struct heap{
    int ar[MAX];
    int rear;
    void ch(int a,int b){
        int t=ar[a];
        ar[a]=ar[b];
        ar[b]=t;
    }
    void upset(int n){
        if(n<2||n>=rear)return;
        int t=n>>1;
        if(t>0&&ar[t]<ar[n]){
            ch(t,n);
            upset(t);
        }
    }
    void downset(int n){
        if(n<1||n>=rear)return;
        int t=n<<1,opt;
        if(t<rear&&ar[n]<ar[t]){
            opt=t+1<rear&&ar[t]<ar[t+1];
            ch(t+opt,n);
            downset(t+opt);
        }
        else if(t+1<rear&&ar[n]<ar[t+1]){
            ch(t+1,n);
            downset(t+1);
        }
    }
    void push(int n){
        ar[rear++]=n;
        upset(rear-1);
    }
    int pop(){
        int t=ar[1];
        ch(1,--rear);
        downset(1);
       
        return t;
    }
}h;
struct seg{
    int cal,t;
    void get(){
        scanf("%d%d",&cal,&t);
    }
    bool operator<(const seg &b)const{
        return t>b.t;
    }
}s[MAX];
int main(){
    scanf("%d",&n);
    cnt=0;h.rear=1;
    for(int i=0;i<n;i++)
        s[i].get();
    scanf("%d",&ed);
    std::sort(s,s+n);
    for(int i=ed;i>0;i--){
        for(;cnt<n&&s[cnt].t>=i;cnt++){
            h.push(s[cnt].cal);
        }
        if(h.rear>1)
            weight+=h.pop();
        else weight--;
    }
    printf("%d\n",weight);
}


2010年3月3日 星期三

TIOJ 1155 4.經濟編碼 [93全國賽(prob 4)]

68011    poao899    1155    Accepted    12K    75MS    G++    0.96K    2010-03-03 22:41:27                 .




噢哈好久沒寫TIOJ了XD

單純Heap這樣

是說 Heap又長得跟之前不一樣了XD

#include<stdio.h>
#define MAX 100010
struct heap{
    double ar[MAX];
    int rear;
    inline void change(int n,int m){
        double t=ar[n];
        ar[n]=ar[m];
        ar[m]=t;
    }
    void upset(int n){
        if(n<2 || n>=rear)return;
        int t=n/2;
        if(ar[t]>ar[n]){
            change(t,n);
            upset(t);
        }
    }
    void downset(int n){
        if(n<1 || n>=rear)return;
        int t=n*2;
        for(int i=0;i<2;i++)
            if(t+i<rear&&ar[n]>ar[t+i]){
                change(t+i,n);
                downset(t+i);
            }
    }
    inline void push(double a){
        ar[rear]=a;
        upset(rear++);
    }
    inline double pop(){
        if(rear==1)return 0;
        double x=ar[1];
        change(1,--rear);
        downset(1);
        return x;
    }
}h;
int n;
char buffer[100];
double total,t;
int main(){
    gets(buffer);
    sscanf(buffer,"%d",&n);
    h.rear=1;
    while(n--){
        gets(buffer);
        sscanf(buffer,"%*c %lf",&t);
        h.push(t);
    }
    for(;;){
        t=h.pop()+h.pop();
        if(h.rear==1)break;
        total+=t;
        h.push(t);
    }
    printf("%.2lf\n",total+t);
    //main();
}