2014-8-5 noip(霧)模擬賽
皇帝的煩惱(二分答案)
Description
經過多年的殺戮,秦皇終於統一了中國。為了抵禦外來的侵略,他準備在國土邊境安置n名將軍。不幸的是這n名將軍羽翼漸豐,開始展露他們的狼子野心了。他們拒絕述職、拒絕接受皇帝的聖旨。秦皇已經準備好了秘密處決這些無禮的邊防大將。不過為防兵變,他決定先授予這些將軍一些勛章,為自己贏得戰略時間。將軍們聽說他們即將被授予勛章都很開心,他們紛紛上書表示感謝。第i個將軍要求得到ai枚不同顏色的勛章。但是這些將軍都很傲氣,如果兩個相鄰的將軍擁有顏色相同的勛章他們就會認為皇帝不尊重他們,會立即造反(編號為i的將軍和編號為i+1的將軍相鄰;因為他們駐紮的邊境可以類似看成一個圓形,所以編號
第一行有一個整數n(1<=n<=20000)。接下來n行每行一個整數ai,表示第i個將軍要求得到多少種勛章。(1<=ai<=100000) 輸出一個整數,即最少需要多少種勛章。
Sample Input
4 2 2 1 1
Sample Output
4
/* 寫了個最大相鄰和,剛寫完就覺得不踏實。。。結果只得了60分 真是巧妙的做法T T 從前往後推出每個人最少/最多有幾個和第一個人相同的勛章 然後看最後一個最少是否是0即可二分答案*/ #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,ans,v[100001],a[100001],b[100001]; bool jud(int x) { a[1]=b[1]=v[1]; for(int i=2;i<=n;i++) { b[i]=min(v[i],v[1]-a[i-1]); a[i]=max(0,v[1]+v[i]+v[i-1]-b[i-1]-x); }return a[n]==0; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&v[i]); ans=max(v[i]+v[i-1],ans); } int l=ans,r=ans*2; while(l<=r) { int mid=(l+r)>>1; if(jud(mid))r=mid-1; else l=mid+1; } printf("%d",l); return 0; }
二叉樹
【Description】
現在有一棵二叉樹,所有非葉子節點都有兩個孩子。在每個葉子節點上有一個權值(有n個葉子節點,滿足這些權值為1..n的一個排列)。可以任意交換每個非葉子節點的左右孩子。
要求進行一系列交換,使得最終所有葉子節點的權值按照中序遍歷寫出來,逆序對個數最少。
【Input Format】
第一行n
下面每行,一個數x
如果x==0,表示這個節點非葉子節點,遞歸地向下讀入其左孩子和右孩子的信息,
如果x!=0,表示這個節點是葉子節點,權值為x。
【Output Format】
一行,最少逆序對個數。
【Sample Input】
3
0
0
3
1
2
【Sample Output】
1
【Hint】
對於30%的數據:2<=n<=5000。
對於100%的數據:2<=n<=200000。
夢幻布丁
Description
N個布丁擺成一行,進行M次操作.每次將某個顏色的布丁全部變成另一種顏色的,然後再詢問當前一共有多少段顏色.例如顏色分別為1,2,2,1的四個布丁一共有3段顏色.
Input
第一行給出N,M表示布丁的個數和好友的操作次數. 第二行N個數A1,A2...An表示第i個布丁的顏色從第三行起有M行,對於每個操作,若第一個數字是1表示要對顏色進行改變,其後的兩個整數X,Y表示將所有顏色為X的變為Y,X可能等於Y. 若第一個數字為2表示要進行詢問當前有多少段顏色,這時你應該輸出一個整數. 0
Output
針對第二類操作即詢問,依次輸出當前有多少段顏色.
Sample Input
4 3
1 2 2 1
2
1 2 1
2
Sample Output
3
1
數據範圍
n,m<=100000 x,y<=1000000
/* 好吧我承認,又亂搞了一個題 就是每次修改都在兩個數組裏倒騰倒騰,順便記錄下答案 40分,剩下的點T了 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,a[100010],b[100010],ch,sza,szb,ansnow,pan; void change(int op,int s,int t){ if(s==t&&pan)return; if(op==0){ memset(b,0,sizeof(b));ansnow=0;szb=0; for(int i=1;i<=sza;i++){ if(a[i]==s)a[i]=t; if(a[i]!=a[i-1]){ ansnow++; b[++szb]=a[i]; } } ch=!ch; return; } if(op==1){ memset(a,0,sizeof(a));ansnow=0;sza=0; for(int i=1;i<=szb;i++){ if(b[i]==s)b[i]=t; if(b[i]!=b[i-1]){ ansnow++; a[++sza]=b[i]; } } ch=!ch; return; } } int main(){ //freopen("Cola.txt","r",stdin); freopen("pudding.in","r",stdin); freopen("pudding.out","w",stdout); scanf("%d%d",&n,&m);sza=n; for(int i=1;i<=n;i++)scanf("%d",&a[i]); change(ch,1,1);//ch=0把a數組轉化到b數組中 pan=1; int op,x,y; for(int i=1;i<=m;i++){ scanf("%d",&op); if(op==2)printf("%d\n",ansnow); if(op==1){ scanf("%d%d",&x,&y); change(ch,x,y); } } return 0; }40分 亂搞
書架
Description
小T有一個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裏的書是從上至下堆放成一列。她用1到n的正整數給每本書都編了號。 小T在看書的時候,每次取出一本書,看完後放回書櫃然後再拿下一本。由於這些書太有吸引力了,所以她看完後常常會忘記原來是放在書櫃的什麽位置。不過小T的記憶力是非常好的,所以每次放書的時候至少能夠將那本書放在拿出來時的位置附近,比如說她拿的時候這本書上面有X本書,那麽放回去時這本書上面就只可能有X-1、X或X+1本書。 當然也有特殊情況,比如在看書的時候突然電話響了或者有朋友來訪。這時候粗心的小T會隨手把書放在書櫃裏所有書的最上面或者最下面,然後轉身離開。 久而久之,小T的書櫃裏的書的順序就會越來越亂,找到特定的編號的書就變得越來越困難。於是她想請你幫她編寫一個圖書管理程序,處理她看書時的一些操作,以及回答她的兩個提問:(1)編號為X的書在書櫃的什麽位置;(2)從上到下第i本書的編號是多少。
Input
第一行有兩個數n,m,分別表示書的個數以及命令的條數;第二行為n個正整數:第i個數表示初始時從上至下第i個位置放置的書的編號;第三行到m+2行,每行一條命令。命令有5種形式: 1. Top S——表示把編號為S的書房在最上面。 2. Bottom S——表示把編號為S的書房在最下面。 3. Insert S T——T∈{-1,0,1},若編號為S的書上面有X本書,則這條命令表示把這本書放回去後它的上面有X+T本書; 4. Ask S——詢問編號為S的書的上面目前有多少本書。 5. Query S——詢問從上面數起的第S本書的編號。
Output
對於每一條Ask或Query語句你應該輸出一行,一個數,代表詢問的答案。
Sample Input
10 10
1 3 2 7 5 8 10 4 9 6
Query 3
Top 5
Ask 6
Bottom 3
Ask 3
Top 6
Insert 4 –1
Query 5
Query 2
Ask 2
Sample Output
2
9
9
7
5
3
數據範圍
30%的數據,n,m < = 10000
100%的數據,n,m < = 80000
2014-8-5 noip(霧)模擬賽