2010年12月7日 星期二

Practice : Asia Beijing 2008 / 2009

北京賽區。據說當年五題+不錯的Penalty就可以拿到金獎  雖然不知道金獎怎麼定義XDD                             .





Beijing (China)


 
ID
Problem Title Download Hint Ranking
4322 Destroying the bus stations

4323 A simple stone game

4324 Ugly Windows

4325 Tornado

4326 Minimal Ratio Tree

4327 Parade

4328 Priest John's Busiest Day

4329 Ping pong

4330 Timer

4331 Elevator





pA 給你一張有向圖(V=50 E=4000)和K,問至少要拔幾個點才使得1->N的最短路大於等於K
(邊權皆為1、1->N沒有直接連邊)

用最大流想法:增廣到該次最短路長度>=K就結束,輸出目前源點流量   不過依然WA

pB給你N和K,兩人輪流取石頭,第一個人第一次只能拿1~N-1顆、
以後每個人每次拿的數量不能超過上衣個人K倍,問先手必勝的第一步?

沒想法,不過應該是經典題

pC給你一張NxM圖片,問你有幾個矩形框在最上層?

模擬,但是注意回字型。

pD有一個龍捲風路徑是一條射線,給你他的速度,還有一個人在兩點之間等速往復運動,問龍捲風到人的最近距離?

沒想法

pE給一張無向有權完全圖,你要輸出一組M個點的生成樹且邊權和/點權和最小,且點排好後的字典序最小。

爆搜,注意一下精度問題。

pF給一張NxM網格(N=100,M=10000),橫向(M方向)每條路徑都有兩個權重,v跟k。
從最底下任意一點開始,到最上面任意一點。只能往上或左右走,且走過路徑不能再走,
且每層(依照N分層)走過的路徑sum k要小於給定的K,求出整條路徑sum v的最大值。

DP,每層轉移需要Deque,不過我還在WAorz

pG給你很多區間(N=100000)代表婚禮,牧師必須選擇一段連續段來進行證婚。
這段必須要大於區間大小的一半,且牧師只有一個人不能分身,問有沒有可能替所有婚禮證婚?

Greedy (by worm),還不會

pH給你一個序列ar(長度=100000),問有幾個三數對A,B,C符合位置A<B<C且ar[B]介於ar[A]和ar[C]之間。

頗裸的Binary Indexed Tree

pI, pJ沒看題目


總體而言打得很失敗orz

不過要感謝suhorng, jurrasickill

2010年12月6日 星期一

TIOJ 1516 Problem F. HALLO ☆ GAME [Binary Tree]

3    91671    poao899    18388K    2197MS    G++     3.18K     2010-12-07 01:07:12                                            .


                                              


因為要正名(?)所以就不用Segment Tree這個名詞了XD

其實我覺得叫做Segment Tree也沒什麼不好,這種東西這麼常用總該有個名字吧XD

而且為什麼歪果仁講的就是正確的大陸人講就是亂講(?)


或許我跟這些都不熟上面只是我一廂情願罷了XD


反正以後這種東西在我的部落格上都會紀錄為Binary Tree?



這題操作很多,不過不難寫。

只需要有三個操作:

區間覆蓋、區間詢問、單點求值就好了。



不過這題還是值得推薦的?

因為它有用到存左邊右邊中間再meld的概念還有大陸學生口中的延遲標記(或sb標記?)

還有有些操作不能純用樹來作XD




仔細想了一下,似乎一棵純粹的Splay Tree可以支援所有操作?

因為那個旋轉說實話我搞了一個禮拜xD







2010年9月12日 星期日

[文件] about Miller-Rabin & Pollard-ρ

※前言

關於質數,台灣競賽方面似乎比較少提及,頂多學學篩法、根號檢驗法而已。

草提一下這兩個算法:



>>埃氏篩法:




//什麼毛啦顏色傳上來變得醜死了


O(N ln N)時間複雜度、O(N)記憶體,求出1~N所有的質數。

    一些優化:

        1. 僅 型如 6n ± 1 者有可能是質數(2 | 6n+2、3 | 6n+3、2 | 6n+4)

        其實這個優化加下去已經可以達到一定速度了。


        2. 用位元壓縮,記憶體僅需要(N/32)個int(排掉偶數可以剩下N/64,但個人認為沒必要)

    一些應用:

        1. 求出質因數個數:

            值得注意的是I = i*i要改成I = i+i才行。

        2. 求Φ(n):

            即找出1~n-1中有幾個跟n互質的數。

            因為有Φ(n) = n * Π(1 - (1/p))     對每個質數p | n,所以可以用篩法作到。



// 另外,線性篩法我不會,所以省略...

相關題目:
    TIOJ:1036、1260、1353、1514、1535
    ACM:294




>>根號檢驗法:




O(√n)檢驗一個數是否為質數。

    一些應用:

        1. 質因數分解:

            每次除到不能除,若<= √p都試完了剩下的那個一定是質數。


相關題目:
    ACM:583



反正目前為止的台灣競賽幾乎都只注重以上兩者,相關題目也十分罕見(目前為止沒見過)

但是對於密碼學而言,以上算法都還不能讓人滿意。




>>Miller-Rabin:

一個能期望極快的判斷質數作法。

算法核心:

引理一:若p是質數,則a(p-1) mod p = 1 (費瑪小定理)

引理二:若x2 mod p = 1(其中x<p、p是質數)那x = p-1或x = 1 (證明就是用(x+1)(x-1) = kp)

然後若我們要測定n是否能通過以a為底的米勒拉賓測試
先把n-1 = 2r * d , 其中d是奇數   也就是求出n-1最高含2的幾次方



那麼   如果 a (2r * d) mod n 不是1  就一定是合數 (引理一)
       就繼續下去a (2(r-1) * d) mod n 得是n-1 或1(引理二)
       如果是n-1即是通過檢測,如果是1就繼續遞迴直到 ad mod n


對int範圍的數字,只需要測 a = 2, 7, 61
對10^16內的數字,只需要測 a = 2, 3, 5, 7, 11, 13, 17, 61, 24251



所以只需要寫一個大數次方 + 主程序大概 20~30 行很OK。


虛擬碼就不附了,上次寫得爛爛的。

進一步可以參照Matrix67的相關文章。




>>Pollard-ρ:

還在學...

2010年9月10日 星期五

PKU 1286 Necklace of Beads [Pólya]

poao899    1286    Accepted    404K    0MS    G++    416B    2010-09-10 23:20:57                                          .



Pólya超經典題。

長為n<24的項鍊,三種顏色定義不同構為旋轉 翻轉<b>擇一</b>後不一樣者。


就套Pólya:

( Σ(i=1...n)(3^gcd(i, n)) + 翻轉 ) / 2n



反正學過真的就水過。






2010年9月5日 星期日

NTUJ 1021 Highway Patrol

36916    1021 - Highway Patrol    poao899    Accepted    C++    0.030    2010-09-05 19:41:21                            .



好題欸@@



題意:

一個大都會內有N座城市(<=100),有M條單行道(<=1,000)

每個單行道可以用一個數組(u, v, p, s, x)表示,表示有一條道路從u往v,

如果要派軍隊巡邏要花費p的代價、裝監視器要s的代價 (0 <= p,s <= 1,000,000)

x代表這條道路的重要性,1表示極為重要,不可以用監視器。


因為這個大都會治安很差,每條道路都必須選擇上述兩種方式之一維持治安品質。

但是,每個軍隊巡邏完了要能回到自己的城市休息,所以我們希望每個城市出分枝度 == 入分枝度。

而且,市民們也不希望看到一個全部僅由監視器戍守的城市,所以至少得有一條路是巡邏。


問最少需要花多少錢滿足以上要求。





Input:

第一行有一個數字T表示測資筆數(T <= 70)

每筆測資第一行是N, M,接下來M行每行有五個數字u, v, p, s, x。


Output:

第i筆測資輸出Case [i]: [cost]

[i]表示測資筆數,[cost]表示你所花的錢,無解請用"impossible取代"。



Sample input:

3
4 5
1 2 10 25 0
2 3 10 5 0
3 1 10 5 0
2 4 10 5 0
4 3 30 5 0
4 5
1 2 10 25 0
2 3 10 5 0
3 1 10 5 0
2 4 10 5 0
4 3 30 5 1
2 1
1 2 10 25 1

Sample output:
Case 1: 40
Case 2: 65
Case 3: impossible























=================Solution================





簡單的先捏一下,flow。





因為把這個問題轉化一下可以想到,你可以假設一開始全部監視,那這樣總cost是Σ(si)。

然後每把一個邊變成巡邏的cost會是(pi-si)。

而且最後答案一定巡邏的邊會形成好幾個環。

所以就一直找全局最小環加上去,加到那個環是正的為止。

進一步會發現,變成有負圈的圖形每次尋找全局最小簡單環。不過很可惜這個題目沒多項式作法。



所以要換一個想法。


可以先把p便宜的邊先巡邏、s便宜的邊先監視。

然後建起來可替換邊以及他的替換代價,容量都是1

然後對每個點,檢查有幾個巡邏出發/幾個巡邏回來   其中的相差就建到S/E,cost=0,容量是差。

作一次帶權flow,算出答案...



然後還要檢查答案是否合法:如果==Σ(si)那就表示你一個邊都沒取

所以Warshall一次,找出最小圈輸出









2010年9月2日 星期四

PKU 2540 Hotter Colder [CG]

7564334    poao899    2540    Accepted    424K    0MS    G++    3998B    2010-09-02 22:09:01                         .



CG題好硬QQ不過應該是打定了XD寫起來頗有成就感(?)

看那精美的code length(望

不過   看到這題還是會想到IOI那個吧XD





題目大意:

有個房間,大小10*10

你一開始站在(0,0),某個位置有一個熱源。

接下來每次你會移動到任意一個座標,然後會告訴你感覺Hotter還是Colder還是Same

每次移動輸出一個數字表示  "熱源可能位置"  的面積。

保證不會移動超過50次。





Sample Input:

10.0 10.0 Colder
10.0 0.0 Hotter
0.0 0.0 Colder
10.0 10.0 Hotter

Sample Output:

50.00
37.50
12.50
0.00



















===============解題報告===============


等於每次對多邊形切一條線,問面積。

測資很小所以可以每次把所有點掃過一遍。


幾個要注意的地方:

1.  判斷交點要注意等於0的狀況= =
2. 把兩個交點去修正多邊形時要注意加入的順序。
3. 注意如果重複點加入多邊形,會爆炸。




大概差不多這樣吧xD




2010年8月29日 星期日

POI - PA 2010 Round 2 Coins

翻譯:

給你n, k還有一個由R, O組成的長度n的序列。

找出區間[i, j]使得這個區間內O的個數是R的k倍,這個區間最長能多長

n, k <= 1,000,000


Sample Input:
15 3
RORROOROOROOORO



Sample Output:
8





solution:

這題跟之前USACO一題有異曲同工之感。

http://acm.pku.edu.cn/JudgeOnline/problem?id=3274

定義f(i) = 1~i出現多少個R - (i/(k+1))

那麼會發現,若f(a) == f(b)則 [a+1, b]必為合法區間

排序 O(n lg n)或Hash O(n)就結束了。

蝴蝶作法雖然核心一樣不過細節完全不同,雖然一樣O(n lg n)


POI 11th Spies

題外話:

這題是POI XI Stage I當年第二多人寫出來的題目


最多那題沒有放在main上面QQ


當年這題 190/334 個滿分,不過我覺得這題明明沒有簡單到這種程度= =


// 好罩電波一定覺得是秒殺題


噢然後,Example裡面有一個1打成小寫L,我在想怎麼一直RE





翻譯:

BIA僱用了很多間諜,每個間諜都被下令要監視其他另一個間諜。

KB想要選一些間諜去進行絕密任務,而且他希望能委任越多間諜越好。

然而這個任務太重要了,所以他希望每個被委任的間諜都至少被一個沒有參與任務的間諜
監視。(而且目前的跟監關係不能變動。)


輸入第一行含一個數字n <= 1,000,000,表示共有n個間諜,接下來會有n行

第i+1行會有一個數字Ai,表示間諜i的跟監對象是Ai。

輸出包涵一個數字K,表示最多可以委任K個間諜並符合題目要求。



Example:
6
2
3
1
3
6
5

the correct result is:
3

===================================題解========================





保證每個點都只會有一條連出去的邊,所以每個連通塊一定是一些鍊,

然後有可能在末尾出現一個環。


對於那些鍊,有一個很明顯而且好證的貪心法就是:


1. 如果那個點入分枝度為零,不能取
2. 如果進入那個點的所有點中有任何一個沒有被取的,那麼他就可以取

然後再來處理每個環:

1. 如果那個環所有點入分枝度都是1 -> 可以取  環長/2 取高斯個點
2. 如果那個環有些點入分枝度 > 1 且有至少一個進入他的點沒被取  那他也可以取
   然後剩下的點依照跟鍊一樣的邏輯取完。


總複雜度 O(V)



COCI 2009/2010 #3 p5

標題好長XD


簡單的說

第一行有兩個數字N, C

接下來給你一條數列S  ,長度是N(<=300,000),裡面的數字範圍是1~C(<=10,000)

第三行是一個數字M(<=10,000)表示有幾組詢問

接下來M組詢問,每組有L, R(1<=L<=R<=N)

問你閉區間[L, R]中有沒有哪個數字出現超過一半?有的話問是哪個數字?

Sample input:
10 3
1 2 1 2 1 2 3 2 3 3
8
1 2
1 3
1 4
1 5
2 5
2 6
6 9
7 10

Sample output:
no
yes 1
no
yes 1
no
yes 2
no
yes 3


全國賽那天晚上戰的COCI的題目(轉

小鬼當時說他會做了不知道跟官方solution一不一樣(欸

shik表示:蒙地卡羅應該會過


不過官方solution好好玩(打滾











========================solution===================


先不要考慮原題目,來想另一個遊戲:

給你一個序列S,每次可以把S裡面相異兩個數字抹掉。

直到全部都剩下同一個數字時遊戲結束

例如 12312323->312323->1323->33m 時結束。

這時紀錄兩個數 candi表示剩下的數字是什麼  count表示結束狀態多長

例如上述例子   candi=3 count=2




引理:如果有個數字出現超過length/2次,那他一定會是candi,無論過程

那麼,我們只要維護一棵seg tree就可以作到區間查詢candi了ˇ

就是分L.candi==R.candi以及L.candi!=R.candi時比兩個count大小

然後求出這個區間的candi,再去用另一棵seg tree計算他出現幾次

如果出現>length/2次就是yes  否則則是no








2010年6月22日 星期二

IOI &#39;05 Mean Sequence

這題被小乃瞬秒XD    不過其實還頗有趣的                                                                                                         .


Description:

定義一個數列S的Mean序列M:

Mi = (Si + S(i+1))/2

例如   序列1, 1, 3, 5, 15的M為: 1, 2, 4, 10



給你一個有n項的序列M,請問有多少S使得

1. S的Mean序列為M

2. S1 <= S2 <= S3 <= ... <= S(n+1)


n<= 5,000,000







Solution:

M2-M1 = (S3-S1)/2

依此,可以把奇數項和偶數項分開討論,例如範例就變成

(a), (b), (a+2), (b+4), (a+14)

再由條件2.

(a)<= (b)<= (a+2)<= (b+4)<= (a+14)

解不等式  加上a+b = 2(M1)驗證


總複雜度O(n)



2010年6月19日 星期六

IOI &#39;06 Joining Points

這題沒有Judge,所以自己寫了一個應該是可以AC的啦XD                                                                           .




很棒的題目。


Description:


Joining Points是一個獨人遊戲。

平面上有g個綠點  r個紅點   (2 <= g,r <= 50 000)

所有點都是整數座標   座標範圍是0~s (s <= 200 000 000)


保證(0,s)和(s,s)有綠點  (s,0)和(0,0)有紅點 並且任三點不共線

遊戲勝利的條件是  用g-1條線段把所有綠點連起來  用r-1條線段把所有紅點連起來

並且所有線段不交叉(共端點不算交叉)

保證一定有解  請輸出任意一種連線方案


Input

第一行: 整數g。接下來g行: 從綠點的編號1開始到g,每一行有二個以空白隔開的整數,
代表一個綠點的xi與yi 座標。第g+2行: 整數 r。接下來r行: 從紅點的編號1開始到r,
每一行有二個以空白隔開的整數,代表一個紅點的xi與yi 座標。

Output

共應輸出g-1+r-1行
每行包含兩個整數一個字元   前兩個整數代表這條線段所連接兩點編號
字元表示所連接兩點顏色


Sample Input
6
0 1000
1000 1000
203 601
449 212
620 837
708 537
8
0 0
1000 0
185 300
314 888
416 458
614 622
683 95
838 400


Sample Output
1 3 g
3 1 r
3 5 r
4 6 r
6 5 r
4 6 g
1 2 g
1 2 r
5 2 g
2 6 g
7 8 r
8 2 r



Solution:






這題目是很棒的D&C。時間複雜度:O(n lg n)


核心思想:

考慮一個三角形  v1 v2 v3 ,其中 v1,v2同色   v3異色

(1)如果中間沒有其他點    結束
(2)如果中間全部剩下的點同色    把那些點全部連到同一個頂點    結束
(3)其他:
選出一個跟v3同色的內部點vp,連v3-vp
然後對v1,v2,vp    v2,v3,vp   v3,v1,vp遞迴



很顯而易見遞迴三角形個數是和(g+r)同數量級,

如果對每個三角形O(g+r)檢查,就有了一個O((g+r)^2)算法   值55分


但是可以發現,其實對同一層    只需要合計O(g+r)的複雜度就可以
總共不會超過lg級別層,所以複雜度O(n lg n)ˇ



至於實做,我是以串列實做。










code(Judge程式,會告訴你是哪裡出錯)

http://codepad.org/rwc0RnZq

對了提一下,檢查是用Disjoint Set確定連通性,Sweep Line Algorithm檢查是否有交點




code(AC code)

http://codepad.org/q6v18QD5




testdata / solution (official)

http://olympiads.win.tue.nl/ioi/ioi2006/contest/day2/points/










2010年5月12日 星期三

IOI &#39;07 Pairs

2    75971    poao899    49440K    4656MS    G++     3.16K     2010-04-26 08:47:55                        .



Inspired by warehouse?

不過三維作法很有趣,竟然有一個n維曼哈頓轉Chebyshev distance的作法,


可惜依現在硬體技術,作用有限

事實上這兩個都有優點,可惜自由轉換僅限於1或2維

算是個遺憾吧(?

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

#include<algorithm>
#define N 100010
#define lb(x) ((x)&-(x))
struct ele{
    int i, j, k, w, x, y, z;
    void _2get();
    void _3get();
}_ar[N];
int ar[N], front, rear;
int b, n, d, m, nmax; long long ans;
int getint(){
    int g=0; char 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;
}
//case 2
#define _2LEN 75010
void ele::_2get(){
    i= getint(); j= getint();
    x= i+j; y= i-j;
}
bool _2cmp(ele a, ele b){
    return a.y<b.y;
}
int _2bit[_2LEN*3];
inline int _2qry(int a){
    if(a<0) return 0;
    int ret= 0;
    while(a>0){
        ret+= _2bit[a];
        a-= lb(a);
    }
    return ret;
}
inline int _2find(int l, int r){
    return _2qry(r)-_2qry(l-1);
}
inline void _2adj(int a, int r){
    while(a<=nmax){
        _2bit[a]+= r;
        a+= lb(a);
    }
}
//case 3
#define _3LEN 76
void ele::_3get(){
    i= getint(); j= getint(); k= getint();
    w= i-j-k; x= i+j-k+m; y= i-j+k+m; z= i+j+k;
}
bool _3cmp(ele a, ele b){
    return a.w<b.w;
}
int _3bit[_3LEN*3+1][_3LEN*3+1][_3LEN*3+1];
inline int _3qry(int x, int y, int z){
    int ret= 0;
    for(int xx=x; xx>0; xx-=lb(xx))
        for(int yy=y; yy>0; yy-=lb(yy))
            for(int zz=z; zz>0; zz-=lb(zz))
                ret+= _3bit[xx][yy][zz];
    return ret;
}
inline int _3find(int lx, int ly, int lz, int rx, int ry, int rz){
    if(rx> nmax)rx= nmax;
    if(ry> nmax)ry= nmax;
    if(rz> nmax)rz= nmax;
    int ret= _3qry(rx,ry,rz);
    ret= ret- _3qry(lx-1,ry,rz)- _3qry(rx,ly-1,rz)- _3qry(rx,ry,lz-1);
    ret= ret+ _3qry(rx,ly-1,lz-1)+ _3qry(lx-1,ry,lz-1)+ _3qry(lx-1,ly-1,rz);
    ret= ret- _3qry(lx-1,ly-1,lz-1);
    return ret;
}
inline void _3adj(int x, int y, int z, int r){
    for(int xx=x; xx<=nmax; xx+=lb(xx))
        for(int yy=y; yy<=nmax; yy+=lb(yy))
            for(int zz=z; zz<=nmax; zz+=lb(zz))
                _3bit[xx][yy][zz]+= r;
}
int main(){
    b= getint(); n= getint(); d= getint(); m= getint();
    //case 1
    if(b==1){
        for(int i=0; i<n; i++) ar[i]= getint();
        std::sort(ar, ar+n);
        for(front=rear=0; rear<n; rear++){
            while(ar[front]+d< ar[rear]) front++;
            ans+= rear-front;
        }
    }
    //case 2
    else if(b==2){
        nmax= _2LEN*3;
        for(int i=0; i<n; i++) _ar[i]._2get();
        std::sort(_ar, _ar+n, _2cmp);
        for(front=rear=0; rear<n; rear++){
            while(_ar[front].y+d< _ar[rear].y){
                _2adj(_ar[front].x, -1);
                front++;
            }
            ans+= _2find(_ar[rear].x-d, _ar[rear].x+d);
            _2adj(_ar[rear].x, 1);
        }
    }
    //case 3
    else if(b==3){
        nmax= _3LEN*3;
        for(int i=0; i<n; i++) _ar[i]._3get();
        std::sort(_ar, _ar+n, _3cmp);
        for(front=rear=0; rear<n; rear++){
            while(_ar[front].w+d< _ar[rear].w){
                _3adj(_ar[front].x, _ar[front].y, _ar[front].z, -1);
                front++;
            }
            ans+= _3find(_ar[rear].x-d, _ar[rear].y-d, _ar[rear].z-d, _ar[rear].x+d, _ar[rear].y+d, _ar[rear].z+d);
            _3adj(_ar[rear].x, _ar[rear].y, _ar[rear].z, 1);
        }
    }
    printf("%I64d\n", ans);
}




POI 13rd Warehouse

25-04-10   14:01       Warehouse      OK           100                                                                              .


有趣的題目XD

很神秘的圖片: 圖片

p=1是曼哈頓距離
p=2是歐式距離
p=∞就是這個題目問的問題了,Chebyshev distance



反正這張圖很好用(?


然後會做了還是會有一個盲點,反正很帥的題目˙//˙

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

#include<algorithm>
int n, i, xx, yy, ax, ay, _x, _y; long long sum, now, t;
struct pl{
int i,j,c,x,y;
void get(){
scanf("%d%d%d", &x, &y, &c);
sum+= (long long)c;
i= x+y;
j= x-y;
}
}p[100000];
bool cmp(pl a, pl b){return a.i<b.i;}
bool cmp2(pl a, pl b){return a.j<b.j;}
int main(){
scanf("%d", &n);
for(i=0; i<n; i++)
p[i].get();
std::sort(p, p+n, cmp);
for(now=0, i=0; i<n; i++){
now+= (long long)p[i].c;
if(now> sum/2){
xx= p[i].i;
break;
}
}
std::sort(p, p+n, cmp2);
for(now=0, i=0; i<n; i++){
now+= (long long)p[i].c;
if(now> sum/2){
yy= p[i].j;
break;
}
}
ax= (xx+yy)/2; ay= (xx-yy)/2;
for(now=9223372036854775807LL,xx=0; xx<2; xx++)
for(yy=0; yy<2; yy++){
int x=ax+xx, y=ay+yy, tx, ty;
for(t=0,i=0; i<n; i++){
tx=(x>p[i].x?x-p[i].x:p[i].x-x);
ty=(y>p[i].y?y-p[i].y:p[i].y-y);
t+= (long long)(tx>ty?tx:ty)*p[i].c;
}
if(t<now){
now= t;
_x= x;
_y= y;
}
}
printf("%d %d\n", _x, _y);
}


POI 14th Offices

24-04-10   15:57       Offices      OK           100                                                                                             .


這題作法好多XD

學了一種新建圖方式,不用struct的adjacent list








反正就是開一個Linked-list 維護沒走過的點

這樣bfs均攤O(V)

//**************************************
#include<algorithm>
#define V 100100
#define E 4000200
int ej[E], st[V], enx[E], n, m, cnt, nxt[V], pre[V], a, b, p, c[V], q[V], v[V];
int s[3000], pp[V];
int main(){
scanf("%d%d", &n, &m);
for(int i=0; i<=n; i++){nxt[i]= i+1; pre[i+1]= i;}
for(int i=1; i<=m; i++){
scanf("%d%d", &a, &b);
ej[i]= b; p= st[a]; st[a]= i; enx[i]= p;
ej[i+m]= a; p= st[b]; st[b]= i+m; enx[i+m]= p;
}
for(int i=1; i<=n; i= nxt[i]){
a=b=0;
q[b]= i; b++;
while(a!=b){
p= q[a]; a++;
v[p]= i; pp[i]++;
for(int j=st[p]; j; j=enx[j])c[ej[j]]= p;
for(int j=nxt[i]; j<=n; j=nxt[j])
if(c[j]!= p){
q[b]= j; b++;
nxt[pre[j]]= nxt[j];
pre[nxt[j]]= pre[j];
}
}
}
for(int i=1; i<=n; i++)
if(v[i]==i){
s[cnt]= pp[i];
cnt++;
}
std::sort(s, s+cnt);
printf("%d\n", cnt);
for(int i=0; i<cnt; i++, putchar(i==cnt? '\n': ' '))
printf("%d",s[i]);
}


TIOJ 1149 4.滿漢全席 [2-SAT]

3    75828    poao899    -8K    75MS    G++     1.01K     2010-04-22 17:40:51                                  .


轉一轉就變2-SAT了


這是2-SAT經典文:按我



其實我覺得最麻煩是建圖很容易建歪˙˙



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

#include<stdio.h>
bool con[40][40], pos, v[40];
char buf[100], c, d;
int n, m, K, a, b, $;
/*
m 0~n-1 h n~2n-1
*/
bool dfs(int now){
v[now]= 1;
if(now-$==n|| $-now==n)return 0;
for(int i=0; i<2*n; i++)
if(con[now][i]&& !v[i]&& !dfs(i))
return 0;
return 1;
}
int main(){
gets(buf);
sscanf(buf, "%d", &K);
while(K--){
pos= 1;
gets(buf);
sscanf(buf, "%d%d", &n, &m);
for(int i=0; i<n*2; i++)
for(int j=0; j<n*2; j++)
con[i][j]= 0;
for(int i=0; i<m; i++){
gets(buf);
sscanf(buf, "%c%d %c%d", &c, &a, &d, &b);
con[a+(c=='h'?n:0)-1][b+(d=='m'?n:0)-1]= 1;
con[b+(d=='h'?n:0)-1][a+(c=='m'?n:0)-1]= 1;
}
for($=0; pos&&$<n; $++){
for(int j=0; j<2*n; j++)v[j]= 0;
pos= dfs($);
if(!pos){
for(int j=0; j<2*n; j++)v[j]= 0;
$+=n; pos= dfs($); $-=n;
}
}
puts(pos? "GOOD": "BAD");
}
}


TIOJ 1204 E.魔法部的任務 [Matching]

17    75514    poao899    1004K    8203MS    G++     0.79K     2010-04-17 21:12:26                       .


DAG 最小路徑覆蓋 == 最大匹配




















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

#include<stdio.h>
int T, n, match[1010], cnt, p[1010][2], t[1010];
bool vst[1010], con[1010][1010];
inline int abs(int a, int b){return a>b? a-b: b-a;}
bool aug(int now){
    if(vst[now]) return 0;
    vst[now]= 1;
    for(int i=1; i<=n; i++)
        if(con[now][i]){
            if(match[i]==-1|| aug(match[i])){
                match[i]= now;
                return 1;
            }
        }
    return 0;
}
int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        cnt= 0;
        for(int i=1; i<=n; i++){
            scanf("%d%d%d", &t[i], &p[i][0], &p[i][1]);
            match[i]= -1;
        }
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                con[i][j]= (i!=j)&& (abs(p[i][0], p[j][0])+ abs(p[i][1], p[j][1])+ t[i]<= t[j]);

        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++) vst[j]= 0;
            if(aug(i)) cnt++;
        }
        printf("%d\n", n-cnt);
    }
}


TIOJ 1204 樹狀的堆積結構 [Cartesian Tree]

4    75128    poao899    456K    156MS    G++     0.86K     2010-04-10 16:01:38                                  .

第一次寫笛卡兒樹

其實比想像好寫(?



//****************************************
#include<stdio.h>
int top, n, cnt;
struct node{
node *lch, *rch;
int val;
}N[10020], *st[10020];
void dfs(node *now){
if(now==NULL)return;
printf("%d%c", now->val, ++cnt==n? '\n': ' ');
dfs(now->lch);
dfs(now->rch);
}
int main(){
N[0].val= -1;
while(~scanf("%d", &n)){
if(!n) break;
cnt= 0;
top= 0; N[0].lch= N[0].rch= NULL;
for(int i=1; i<=n; i++){
scanf("%d", &N[i].val);
N[i].lch= N[i].rch= NULL;
}
st[top]= N;
for(int i=1; i<=n; i++){
while(top> -1&& st[top]->val>N[i].val){
N[i].lch= st[top];
--top;
}
st[top]->rch= &N[i];
st[++top]= &N[i];
}
dfs(N[0].rch);
}
}


TIOJ 1483 電腦檢查 [BIT]

4    75098    poao899    15712K    10230MS    G++     1.06K     2010-04-10 12:42:54                       .


第一次寫樹狀數組

然後就愛上他了˙////////˙




是說一開始陣列開太小一直RE

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

#include<algorithm>
#define MOD 1000000007
#define lb(x) ((x)&(-x))
int bit[1010][1010], r, c, T, cnt;
int qry(int i, int j){
int ret= 0;
for(; i>0; i-=lb(i))
for(int jj=j; jj>0; jj-=lb(jj)){
ret+= bit[i][jj];
ret%=MOD;
}
return ret;
}
void adj(int i, int j, int v){
for(; i<=r; i+=lb(i))
for(int jj=j; jj<=c; jj+=lb(jj)){
bit[i][jj]+= v;
bit[i][jj]%=MOD;
}
}
struct com{
int i,j,h;
bool operator<(const com &b)const{
return h<b.h|| ( h==b.h&& (i>b.i|| i==b.i&&j>b.j ) );
}
void get(int a, int b){
scanf("%d", &h);
i= a; j= b;
}
}cc[1001000];
int main(){
scanf("%d", &T);
while(T--){
scanf("%d%d", &r, &c);
//Init
cnt= 0;
for(int i=1; i<=r; i++)
for(int j=1; j<=c; j++)
bit[i][j]= 0;
for(int i=1; i<=r; i++)
for(int j=1; j<=c; j++)
cc[cnt++].get(i, j);
std::sort(cc, cc+cnt);
for(int i=0; i<cnt; i++){
int ii=cc[i].i, jj=cc[i].j;
adj(ii, jj, qry(ii, jj)+1);
}
printf("%d\n", qry(r, c));
}
}


TIOJ 1136 3.熱鍋上的螞蟻 [Matrix]

76695    nolonger    3136K    1591MS    G++     1.19K     2010-05-12 23:24:38                                .


蚯蚓:「看到範圍10^9不是很明顯嗎?」

然後就瞬間領悟了。


第二題co 矩陣相乘

是說最後模考還是寫爆了orz



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

#include<stdio.h>
bool con[110][110];
int n, t, a, b, cnt[110], c, pre, x;
double tmp[110][110];
struct Matrix{
    double a[110][110];
    void operator*= (Matrix b){
        for(int i=1; i<=t; i++)
            for(int j=1; j<=t; j++)
                tmp[i][j]= .0;
        for(int i=1; i<=t; i++)
            for(int j=1; j<=t; j++)
                for(int k=1; k<=t; k++)
                    tmp[i][j]+= a[i][k]*b.a[k][j];
        for(int i=1; i<=t; i++)
            for(int j=1; j<=t; j++)
                a[i][j]= tmp[i][j];
    }
}n2[40], ans;

int main(){
    while(~scanf("%d%d", &t, &n)){
        if(!n&&!t)break;
        scanf("%d", &c);
        //Init
        for(int i=1; i<=t; i++){
            cnt[i]= 0;
            for(int j=1; j<=t; j++){
                con[i][j]= 0;
                ans.a[i][j]= .0;
            }
            ans.a[1][i]= 1./t;
        }
        //Input
        while(c--){
            scanf("%d%d", &a, &b);
            ++cnt[a]; ++cnt[b];
            con[a][b]= con[b][a]= 1;
        }
        //Construct
        for(int i=1; i<=t; i++)
            for(int j=1; j<=t; j++)
                n2[0].a[i][j]= (cnt[i]&& con[i][j])? (1./cnt[i]): .0;
        //Matrix
        for(pre=1; (1<<pre)<=n; pre++){
            n2[pre]= n2[pre-1];
            n2[pre]*=n2[pre-1];
        }
        //Compute
        for(; pre>=0; pre--){
            if((1<<pre)<=n){
                n-=(1<<pre);
                ans*= n2[pre];
            }
        }
        scanf("%d", &x);
        printf("%.4lf\n", ans.a[1][x]);
    }
}



2010年4月5日 星期一

TIOJ 1249 帳號查詢 [Brute Force]

poao899    1249    Accepted    784K    182MS    G++    1.47K    2010-04-06 01:41:49                              .




 糟糕co好長


猥是猥瑣了些但不難


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

#include<algorithm>
struct str{
    char s[70];
    bool operator<(const str &b)const{
        for(int i=0; i<70; i++){
            if(s[i]> b.s[i])return 0;
            else if(s[i]< b.s[i])return 1;
        }
        return 0;
    }
    void get(){
        gets(s);
        int i=0;
        for(; s[i]&&s[i]!=32; ++i);
        for(; i<70; ++i)
            s[i]= 0;
    }
};
struct name{
    str pre, now;
    void get(){
        pre.get(); now=pre;
        std::sort(now.s, now.s+strlen(now.s));
    }
    bool operator<(const name &b)const{
        return now<b.now || !(now<b.now)&&!(b.now<now)&&pre<b.pre;
    }
}na[7000], t;
struct out{
    str ord;
    int st, ed;
    bool operator<(const out &b)const{
        return ord< b.ord;
    }
}o[7000];
int n, oCnt;
bool can;
char buf[70];
void push(str ord, int st, int ed){
    o[oCnt].ord= ord;
    o[oCnt].st= st;
    o[oCnt].ed= ed;
    ++oCnt;
}
int main(){
    while(gets(buf)){
        sscanf(buf, "%d", &n);
        if(n==0)break;
        oCnt= 0;
        for(int i=0; i<n; ++i)
            na[i].get();
        std::sort(na, na+n);;
        for(int i=0, j; i<n; ++i){
            t= na[i];
            for(j=i; j<n; ++j){
                if(t.now< na[j].now)break;
            }
            if(j>i+1){
                push(na[i].pre, i, j);
                i= j-1;
            }
        }
        if(!oCnt)puts("No Answer");
        else{
            std::sort(o, o+oCnt);
            for(int i=0; i<oCnt; i++){
                for(int j=o[i].st; j<o[i].ed; ++j){
                    if(j!=o[i].st)printf(",");
                    printf("%s", na[j].pre.s);
                }
                puts("");
            }
        }
    }
}


TIOJ 1482 孔明棋 [狀態壓縮]

poao899    1482    Accepted    27640K    227MS    G++    0.79K    2010-04-05 19:42:47                 .


對吼忘了只要記走訪過所以不需要DP= =





















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

#include<stdio.h>
int stat[1<<23][24], n, ss;
char in[20];
inline bool getbit(int q, int st){
    return st& (1<<q);
}
void dp(int st, int n){
    if(stat[st][n])return;
    int cnt=0, t1, t2, t3;
    for(int i=0; i<n; ++i){
        cnt+= getbit(i, st);
    }
    stat[st][n]= cnt;
    for(int i=0; i+2<n; ++i){
        if(getbit(i+1, st)){
            t1= getbit(i, st);
            t2= getbit(i+2, st);
            if(t1^t2){
                t3= st^(1<<(i))^(1<<(i+1))^(1<<(i+2));
                dp(t3, n);
                if(stat[t3][n]< stat[st][n])
                    stat[st][n]= stat[t3][n];
            }
        }
    }
}
int main(){
    while(~scanf("%d\n", &n)){
        gets(in);
        ss= 0;
        for(int i=0; in[i]; ++i)
            ss=(ss<<1)+(in[i]=='o');
        dp(ss, n);
        printf("%d\n", stat[ss][n]);
    }
}


TIOJ 1253 砲打皮皮 [Graph]

poao899    1253    Accepted    392K    166MS    G++    0.67K    2010-04-05 19:03:02                          .




二分圖匹配

交錯路徑算法,O(V^3)


耶總算會co匹配了>//<


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

#include<stdio.h>
int n, k, match[1010], cCnt, mCnt, a, b;
bool con[1010][1010], vst[1010];
bool aug(int now){
for(int i=1; i<=n; i++)
if(!vst[i]&& con[now][i]){
vst[i]= 1;
if(match[i]==-1|| aug(match[i])){
match[i]= now;
return 1;
}
}
return 0;
}
int main(){
while(~scanf("%d%d", &n, &k)){
if(!n&& !k) break;
mCnt= 0;
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; j++)
con[i][j]= 0;
match[i]= -1;
}
for(int i=0; i<k; ++i){
scanf("%d%d", &a, &b);
con[a][b]= 1;
}
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j) vst[j]= 0;
if(aug(i)) ++mCnt;
}
printf("Case #%d:%d\n", ++cCnt, mCnt);
}
}


2010年4月4日 星期日

POI - PA 2008 Studies [A] [Graph]

02-04-10   08:12       Studies [A]      OK           10                                                      .





題目是說

給你一張有向有權圖  V<=300  E<=90000

如果點A能經過一條路徑(可經過重複邊重複點)回到自己 那他就是好的點

請輸出所有好的點









SCC,因為非SCC以外的點絕對沒有影響

全部cost反過來,鈴鐺人只要有負圈就表示這個SCC都可以

(原圖存在正圈)


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

#include<stdio.h>
#include<algorithm>
#define INF 10000000000LL
int color[400], n, m, cCnt, stamp[400], a, b, tt, conv[400], bfCnt, cnt, out[400];
long long c, dist[400];
struct edge{
int i, j;
long long co;
edge *next;
}e[200000], *v[400], *vr[400], e_bf[200000];
bool vis[400], visr[400], canScc[400];
void set(edge **vv, edge *ee, int i, int j, long long c){
edge *p=vv[i];
vv[i]=ee; ee->i=i; ee->j=j; ee->co=c; ee->next=p;
}
void dfs(int n){
vis[n]= 1;
for(edge *p=v[n]; p; p=p->next)
if(!vis[p->j]){
dfs(p->j);
}
stamp[++tt]= n;
}
void dfsr(int n){
visr[n]= 1;
for(edge *p=vr[n]; p; p=p->next){
if(!visr[p->j]){
color[p->j]= color[n];
dfsr(p->j);
}
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i=0; i<m; i++){
scanf("%d%d%lld", &a, &b, &c);
set(v, e+i, a, b, -c);
set(vr, e+i+m, b, a, -c);
}
for(int i=1; i<=n; i++){
dist[i]= INF;
if(!vis[i])
dfs(i);
}
for(int z=tt; z>0; z--){
int i= stamp[z];
if(!visr[i]){
color[i]= ++cCnt;
conv[cCnt]= i;
dist[i]= 0;
dfsr(i);
}
}
for(int i=0; i<m; i++)
if(color[e[i].i]== color[e[i].j])
e_bf[bfCnt++]= e[i];
for(int z=1; z<n; z++)
for(int i=0; i<bfCnt; i++)
if(dist[e_bf[i].j]> dist[e_bf[i].i]+e_bf[i].co)
dist[e_bf[i].j]= dist[e_bf[i].i]+e_bf[i].co;
for(int i=0; i<bfCnt; i++)
if(dist[e_bf[i].j]> dist[e_bf[i].i]+e_bf[i].co)
canScc[color[e_bf[i].i]]= 1;
for(int i=1; i<=n; i++)
if(canScc[color[i]])
out[cnt++]= i;
printf("%d\n", cnt);
for(int i=0; i<cnt; i++, putchar(i==cnt?'\n':' '))
printf("%d", out[i]);
}



TIOJ 1484 仙人掌 [Graph]

poao899    1484    Accepted    824K    947MS    G++    1.89K    2010-04-03 20:44:58                           .



可愛題。

給你一張圖問你是不是符合以下條件

1.  整張圖都在同一個SCC
2.  每條邊只能而且必須屬於一個而且只有一個簡單圈












先做一次SCC

之後作v次DFS拔邊,均攤O(E)


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

#include<stdio.h>
#define MAXV 100100
int T, n, m, stamp, tt, a, b, cnt, eCnt, _tar;
int vst[MAXV], can;
struct edge{
int i, j;
edge *next;
void set(int a, int b, edge **vv){
edge *p= vv[a];
vv[a]= this; i=a; j=b; next= p;
}
}e[MAXV*20], *v[MAXV], *vr[MAXV];
void dfs(int now){
vst[now]= 1;
for(edge *p=v[now]; p; p=p->next)
if(!vst[p->j])
dfs(p->j);
stamp= now; ++tt;
}
void dfsr(int now){
vst[now]= 1; ++cnt;
for(edge *p=v[now]; p; p=p->next)
if(!vst[p->j])
dfsr(p->j);
}
int dfs3(int now){
int t;
vst[now]= _tar;
for(edge *p=v[now],*q=NULL; p; p=p->next){
if(vst[p->j]== _tar){
eCnt++;
if(q)q->next= p->next;
else v[now]= p->next;
return p->j;
}
else{
t= dfs3(p->j);
if(t!=0){
eCnt++;
if(q){q->next= p->next;}
else v[now]= p->next;
if(t!=now){
return t;
}
}else q=p;
}
}
return 0;
}
int main(){
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
//init
for(int i=0; i<=n; i++){
vst[i]= 0;
v[i]= vr[i]= NULL;
}
can= 1; tt= cnt= eCnt= 0;
//input
for(int i=0; i<m; i++){
scanf("%d%d", &a, &b); ++a; ++b;
e[i].set(a, b, v);
e[i+m].set(b, a, vr);
}
//dfs
dfs(1);
if(tt!= n){puts("NO"); continue;}
for(int i=1; i<=n; i++) vst[i]= 0;
dfsr(stamp);
if(cnt!= n){puts("NO"); continue;}
for(int i=1; i<=n; i++) vst[i]= 0;
for(int i=1; i<=n; i++){
_tar= i;
dfs3(i);
}
puts(eCnt== m? "YES": "NO");
}
}




TIOJ 1493 三個農夫

poao899    1493    Accepted    37884K    1510MS    G++    2.79K    2010-04-03 13:49:36                 .


死得亂七八糟==


反正就  壓扁線段樹  但是一直co炸= =





不會Stack Overflow超神奇










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

#include<stdio.h>
#include<stdlib.h>
#define MAXV 1000100
int conv[MAXV][2], _opt, _t, _n, _m, _pos, a, b;
long long  _adj;
char com[100];

template<class T>
T getnum(){
    T get = 0;
    char c = getchar();
    while(c == ' ' || c == '\n') c = getchar();
    while(c > 47 && c < 58){
        get = get * 10 + c - 48;
        c = getchar();
    }
    return get;
}

//Tree
struct edge{
    int j;
    edge *next;
}e[MAXV*2],*v[MAXV];
void set(int i, int j){
    static int cnt=0;
    edge *p= v[i], *q= e+cnt++;
    v[i]= q; q->j= j; q->next= p;
}
//DFS
void dfs(int now){
    conv[now][0]= ++_t;
    for(edge *p=v[now]; p; p=p->next){
        if(conv[p->j][0])continue;
        dfs(p->j);
    }
    conv[now][1]= ++_t;
}
//Segment_Tree 2/e
struct seg{
    int l, r; long long v[3];
    seg *lch, *rch;
    long long qry(int, int);
    void adj();
}s[MAXV*4],*st;
seg* get(int l, int r){
    static int cCnt=0;
    seg *p= s+cCnt++;
    p->l=l; p->r=r; p->v[0]=p->v[1]=p->v[2]=-1; p->lch=p->rch=NULL;
    return p;
}
long long seg::qry(int _l, int _r){
    if(_l<l|| _r>r)return 0;
    if(l==r)return v[_opt]==-1? v[_opt]=0: v[_opt];
    int mid= (l+r)/2;
    if(!lch)return 0;
    if(_l==l&& _r==r){
        if(v[_opt]== -1){
            return v[_opt]= lch->qry(l, mid) + rch->qry(mid+1, r);
        }else return v[_opt];
    }
    if(mid>= _r)return lch->qry(_l, _r);
    else if(mid< _l)return rch->qry(_l, _r);
    return lch->qry(_l, mid) + rch->qry(mid+1, _r);
}
void seg::adj(){
    if(_pos<l|| _pos>r)return;
    int mid= (l+r)/2;
    if(l==r){
        if(v[_opt]== -1)v[_opt]=0;
        v[_opt]+= _adj; return;
    }
    if(!lch){
        lch= get(l, mid);
        rch= get(mid+1, r);
    }
    if(v[_opt]!= -1)v[_opt]+= _adj;
    if(mid< _pos) rch->adj();
    else lch->adj();
}
int main(){
    _n = getnum<int>();
    //Init
    st= get(1, _n*2);
    for(int i=1; i<_n; i++){
        a= getnum<int>(); b= getnum<int>();
        set(a, b); set(b, a);
    }
    //DFS : to Seg Tree
    dfs(1);
    scanf("%d", &_m);
    for(int i=0; i<_m; i++){
        scanf("%s", com);
        switch(com[0]){
            case'Q':
                _pos= getnum<int>();
                a= conv[_pos][0]; b= conv[_pos][1];
                for(_opt=0; _opt<3; _opt++,putchar(_opt==3?'\n':' '))
                    printf("%I64d", st->qry(a,b));
                break;
            case'D':
                _pos= getnum<int>(); _opt=getnum<int>();
                _adj= getnum<long long>();
                a= conv[_pos][0]; b= conv[_pos][1];
                if(_pos==1&& _opt!=2 || _pos!=1&&b==a+1&&_opt==2){
                    puts("Error");
                }else{
                    long long q= st->qry(a, a);
                    //printf("Q %I64d\n", q);
                    if(q>= _adj){
                        _adj= -_adj;
                        _pos= a;
                        st->adj();
                    }else puts("Error");
                }
                break;
            case'G':
                _pos= getnum<int>(); _opt=getnum<int>();
                _adj= getnum<long long>();
                a= conv[_pos][0]; b= conv[_pos][1];
                if(_pos==1&& _opt!=2 || _pos!=1&&b==a+1&&_opt==2){
                    puts("Error");
                }else{
                    a= conv[_pos][0];
                    _pos= a;
                    st->adj();
                }
                break;
        }
    }
}


TIOJ 1603 胖胖殺蚯事件 [ RMQ ]

73346    poao899    5088K    374MS    G++     1.43K     2010-04-02 11:24:19                                       .


SKYLY: 想當年第一次出現這個大家都不會沒想到現在已經平民化了




試寫Segment Tree.


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

#include<stdio.h>
unsigned val[100010], n, q, a, b;
struct seg{
unsigned l, r, v1, v2;
seg *lch, *rch;
unsigned max(unsigned,unsigned);
unsigned min(unsigned,unsigned);
}s[300000];
seg *get(unsigned l, unsigned r){
static int cnt=0;
s[cnt].l=l; s[cnt].r=r; s[cnt].v1=0; s[cnt].v2=222222222u;
return s+cnt++;
}
unsigned seg::max(unsigned _l, unsigned _r){
//printf(">>%u %u\n",l,r);
if(l== r)return v1= val[l];
unsigned m1, m2, mid=(l+r)/2;
if(!lch){
lch= get(l, mid);
rch= get(mid+1, r);
}
if(_l==l&& _r==r){
if(!v1){
m1= lch->max(l, mid);
m2= rch->max(mid+1, r);
v1= m1>m2?m1:m2;
}return v1;
}
if(_l> mid)
return rch->max(_l, _r);
else if(_r<= mid)
return lch->max(_l, _r);
else{
m1= lch->max(_l, mid);
m2= rch->max(mid+1, _r);
return m1>m2?m1:m2;
}
}
unsigned seg::min(unsigned _l, unsigned _r){
if(l== r)return v2= val[l];
unsigned m1, m2, mid=(l+r)/2;
if(_l==l&& _r==r){
if(v2==222222222u){
m1= lch->min(l, mid);
m2= rch->min(mid+1, r);
v2= m1<m2?m1:m2;
}return v2;
}
if(_l> mid)
return rch->min(_l, _r);
else if(_r<= mid)
return lch->min(_l, _r);
else{
m1= lch->min(_l, mid);
m2= rch->min(mid+1, _r);
return m1<m2?m1:m2;
}
}
int main(){
scanf("%u %u", &n, &q);
for(int i=1; i<=n; i++)
scanf("%u", val+i);
get(1, n);
while(q--){
scanf("%u%u", &a, &b);;
printf("%u\n", s[0].max(a,b)-s[0].min(a,b));
}
}

TIOJ 1099 B.射手座之日 [BFS] [NPSC 2006]

poao899    1099    Accepted    24048K    10281MS    G++    1.83K    2010-04-02 10:18:25                 .



本來想寫Bi-BFS的但好像寫炸了

            x+y+z= k            這個剪枝太強大了











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

#include<stdio.h>
#define QLEN 2000000
bool chk[3010][3010][2], can;
int q[QLEN][3], front, rear;
int n, x1, y1, z1, x2, y2, z2, sum, a, b, t1, t2, aa[3];
inline int max2(int i, int j, int k, int &m1, int &m2){
    int max=(i>j)?(i>k?i:k):(j>k?j:k), min=(i<j)?(i<k?i:k):(j<k?j:k);
    m1= min; m2= i+j+k-max-min;
}
inline void push(int x, int y, int op){
    if(x>=0&&x<=n&&y>=0&&y<=n&&(sum-x-y)>=0&&(sum-x-y)<=n){
        if(chk[x][y][!op]){can=1; return;}
        if(!chk[x][y][op]){
            chk[x][y][op]= 1;
            q[rear][0]= x; q[rear][1]= y; q[rear][2]= op;
            rear= ++rear%QLEN;
        }
    }
}
int main(){
    while(~scanf("%d%d%d%d%d%d%d", &n, &x1, &y1, &z1, &x2, &y2, &z2), n){
        if(x1+y1+z1!= x2+y2+z2){puts("No"); continue;}
        sum= x1+y1+z1;
        for(int i=0; i<=n; i++)
            for(int j=0; j<=n; j++)
                chk[i][j][0]= chk[i][j][1]= 0;
        front=0; rear=2; can=0;
        max2(x1,y1,z1,q[0][0],q[0][1]); q[0][2]= 0;
        max2(x2,y2,z2,q[1][0],q[1][1]); q[1][2]= 1;
        chk[q[0][0]][q[0][1]][0]= chk[q[1][0]][q[1][1]][1]= 1;
        while(!can&& front!=rear){
            int x= q[front][0], y= q[front][1], opt= q[front][2];
            if(chk[x][y][!opt]){can=1; break;}
            aa[0]= x; aa[1]= y; aa[2]= sum-x-y;
            if(opt==0){
                for(int i=0; i<3; i++)
                    for(int j=0; j<3; j++){
                        if(i==j)continue;
                        x=aa[i]; y=aa[j];
                        t1= (y*2)-x+1; t2= (x*2)-y-1;
                        max2(t1, t2, sum-t1-t2, a, b);
                        push(a, b, opt);
                    }
            }else{
                for(int i=0; i<3; i++)
                    for(int j=0; j<3; j++){
                        if(i==j)continue;
                        x=aa[i]; y=aa[j];
                        t1= (x*2)+y+1; t2= (y*2)+x-1;
                        if(t1%3==0 && t2%3==0){
                            t1/=3; t2/=3;
                            max2(t1, t2, sum-t1-t2, a, b);
                            push(a, b, opt);
                        }
                    }
            }
            front= ++front%QLEN;
        }
        if(can)puts("Yes");
        else puts("No");
    }
}


TIOJ 1144 5.快遞服務 [95 全國賽]

poao899    1144    Accepted    496K    591MS    G++    1.12K    2010-04-01 16:06:45                          .








狀態   O(n^3 m ) *   轉移  O(     1    )      ==>      狀態   O(n^2 m ) *   轉移  O(     1   


然後就可以過了ˊˇˋ



每個狀態一定要有一個司機在上一個點上嘛ˇ












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

#include<stdio.h>
#define INF 1000000000
struct dp{
    int a[210][210];
}d1, d2, *now, *pre, *tmp;
int m, dist[210][210], n, pn;
int main(){
    now=&d1, pre=&d2;
    scanf("%d", &m);
    for(int i=0; i<m; i++)
        for(int j=0; j<m; j++){
            scanf("%d", &dist[i][j]);
            now->a[i][j]= pre->a[i][j]= INF;
        }
    for(int i=0;;i++){
        if(scanf("%d", &n)==EOF)break;
        --n;
        if(i==0){
            now->a[0][1]= dist[2][n];
            now->a[1][2]= dist[0][n];
            now->a[0][2]= dist[1][n];
        }else{
            for(int j=0; j<m; j++)
                for(int k=0; k<m; k++)
                    if(pre->a[j][k]!= INF){
                        if(now->a[j][k]> pre->a[j][k]+ dist[pn][n])now->a[j][k]= pre->a[j][k]+ dist[pn][n];
                        if(now->a[pn][k]> pre->a[j][k]+ dist[j][n])now->a[pn][k]= pre->a[j][k]+ dist[j][n];
                        if(now->a[pn][j]> pre->a[j][k]+ dist[k][n])now->a[pn][j]= pre->a[j][k]+ dist[k][n];
                        pre->a[j][k]= INF;
                    }
        }
        tmp=pre; pre=now; now=tmp; pn=n;
    }
    int min =INF;
    for(int i=0; i<m; i++)
        for(int j=0; j<m; j++)
            if(pre->a[i][j]< min)
                min= pre->a[i][j];
    printf("%d\n", min);
}


TIOJ 1444 郵局設置問題 [Tree] = UVa 10459

poao899    1444    Accepted    280K    181MS    G++    1.43K    2010-03-31 15:04:42                         .




同UVa 10459The  Tree Root

不過那題輸出好機車= =

Best Roots  : 1
Worst Roots : 4 5 6 7

第一行是兩個空白啦囧囧囧



Tree DP O(n)    結束























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

#include<stdio.h>
#define MAX 1000000
int DP[MAX*2+1],n,sum,max;
int getint(){
    int g=0,c=getchar();
    while(c==10||c==9||c==32)c=getchar();
    if(c==EOF)return -1;
    while(c>='0'&&c<='9'){
        g=g*10+c-48;
        c=getchar();
    }
    return g;
}
int get(){
    char c=getchar();int a=1;
    while(c==10||c==32||c==9)c=getchar();
    if(c=='-')a=-1;
    if(c=='0')a=0;
    while(c!=10)c=getchar();
    return a;
}
main(){
    int *dp=DP;
    while(~(n=getint())){
        for(int i=-n;i<=n;i++)
            dp[i+MAX]=-1;
        sum=max=0;
        dp[MAX]=0;
        for(int i=0;i<n;i++){
            sum+=get();
            dp[sum+MAX]==-1?dp[sum+MAX]=i+1:max>?=i-dp[sum+MAX]+1;
        }
        printf("%d\n",max);
    }
}