flower.cpp/in/out
Time Limit: 1s
Memory Limit: 512MB
Description
小 C 在家種了 n 盆花, 每盆花有一個豔麗度 a i .
在接下來的 m 天中, 天天早晨他會從一段編號連續的花中選擇一盆擺
放在客廳, 並在晚上放回. 同時天天有特定的光照強度 k i , 若是這一天裏擺
放在客廳的花豔麗度爲 x, 則他能得到的喜悅度爲 x mod k i .
他但願知道, 每一天他能得到的最大喜悅度是多少.
Input Format
數據第一行包含兩個正整數 n, m.
接下來一行 n 個正整數, 第 i 個數 a i 表示第 i 盆花的豔麗度.
接下來 m 行, 每行三個正整數 l i , r i , k i , 表示選花區間和光照強度.
Output Format
輸出 m 行, 每行一個整數, 表示最大喜悅度.
Sample Input
5 5
1 2 3 4 5
1 3 2
2
1 3 3
1 4 4
5 5 5
3 5 3
Sample Output
1
2
3
0
2
Constraints
對於 20% 的數據, n, m ≤ 4000.
對於 40% 的數據, n, m ≤ 50000.
對於另外 20% 的數據, a i ≤ 300.
對於 100% 的數據, n, m, a i , k i ≤ 10 5 .
--------------c++
對於每次詢問,直接枚舉便可。複雜度O(n^2)。git
能夠預處理出k=1~300時全部位置的答案,開個桶就好。複雜度O((n+m)*300)數組
考場上想到了分塊,在每一個塊內預處理出k=1~300時的答案,對於k>300的部分,
能夠對每一個塊開一個1e5的數組f,f[i]記錄的是<i的這個塊裏出現的最大數,
這樣,對於給定的k,k-(i-f[i])就有可能成爲最優解。查詢時,對於每一個整塊,
分別令i=k,2k,3k...min(nk,100000),更新答案便可;對於非整塊,暴力就好。
複雜度最壞是O(n^2)。不過實際評測時居然沒有一個點TLE。。。spa
只須要預處理出上述過程的答案就好,複雜度O(n*(nlogn^0.5)),利用均值不等式,
易得出塊大小N=1000時複雜度最優。code
#include<bits/stdc++.h> using namespace std; #define re register int #define F(x,y,z) for(re x=y;x<=z;x++) #define FOR(x,y,z) for(re x=y;x>=z;x--) #define I inline void #define IN inline int typedef long long ll; I read(int &res){ re g=1;register char ch=getchar();res=0; while(!isdigit(ch)){ if(ch=='-')g=-1; ch=getchar(); } while(isdigit(ch)){ res=(res<<3)+(res<<1)+(ch^48); ch=getchar(); } res*=g; } const int N=100000,E=1000; int n,m,L,R,W,sum,X,Y,ans,l[101000],b[101000],f[110][101000],a[101000],len; int main(){ //freopen("flower0.in","r",stdin); //freopen("flower.out","w",stdout); read(n);read(m);len=E;n--; F(i,0,n){ read(a[i]); b[i]=(i/len)+1; } F(i,1,b[n]){ memset(l,0,sizeof(l)); F(j,(i-1)*len,min(i*len,n)){ l[a[j]]=a[j]; } F(j,1,N){ l[j]=max(l[j],l[j-1]); } F(j,1,N){ for(re k=0;k<=N;k+=j)f[i][j]=max(f[i][j],l[min(k+j-1,N)]-k); } } while(m--){ read(L);read(R);read(W);L--;R--; X=b[L];Y=b[R];ans=0; if(X+1<=Y-1){ F(i,X+1,Y-1){ ans=max(ans,f[i][W]); } } F(i,L,min(X*len,R)){ ans=max(ans,a[i]%W); } F(i,max(L,(Y-1)*len),R){ ans=max(ans,a[i]%W); } printf("%d\n",ans); } return 0; } /* 5 5 1 2 3 4 5 1 3 2 1 3 3 1 4 4 5 5 5 3 5 3 */
這題的數據好像有點問題,N只要不是1000就WA。。。
原本個人假程序好像是能夠AC的。。。orm
refract.cpp/in/out
Time Limit: 1s
Memory Limit: 128MB
Description
小 Y 十分喜好光學相關的問題, 一天他正在研究折射.
他在平面上放置了 n 個折射裝置, 但願利用這些裝置畫出美麗的折線.
折線將從某個裝置出發, 而且在通過一處裝置時能夠轉向, 若通過的裝置坐
標依次爲 (x 1 ,y 1 ),(x 2 ,y 2 ),...(x k ,y k ), 則必須知足:
• ∀j ∈ (1,k], y j < y j−1
• ∀j ∈ (2,k], x j−2 < x j < x j−1 or x j−1 < x j < x j−2
如今他但願你能告訴他, 一共有多少種不一樣的光線能被他畫出來, 兩
種光線不一樣當且僅當通過的折射裝置的集合不一樣. 你只須要告訴他答案對
10 9 + 7 取模後的結果.
Input Format
第一行一個正整數 n, 表示折射裝置的數量.
接下來 n 行, 每行兩個整數 x i ,y i 表示折射裝置的座標.
Output Format
輸出一行一個整數, 表示答案對 10 9 + 7 取模後的結果.
Sample Input
4
2 2
3 1
1 4
4 3
Sample Output
14
Constraints
對於 10% 的數據: n ≤ 700,1 ≤ x i ,y i ≤ N
對於 20% 的數據: n ≤ 1000,1 ≤ x i ,y i ≤ N
對於 50% 的數據: n ≤ 4000,|x i |,|y i | ≤ 10 9
對於 100% 的數據: n ≤ 6000,|x i |,|y i | ≤ 10 9
全部數據知足 ∀i ̸= j, x i ̸= x j and y i ̸= y j .排序
考試時只想到n^3暴力,想着能夠騙10分,結果手殘開了個f[6060][6060]沒算空間,直接MLE。。
直接說正解吧。。
首先,確定不能以y座標排序,這樣複雜度只能是n^3。
咱們把全部點按x座標升序排列。枚舉i節點,考慮在已有的折線中加入i。
考慮到i的橫座標是最大的,因此它只多是折線的第一個或第二個。
由於它是折線,咱們天然就想到用左或右來做爲一個dp轉移的狀態。
設f[i][0/1]表示i號節點爲y座標最大值時,折線接下來向左或向右的方案數。
那有哪些節點能夠轉移呢?
考慮枚舉i以前的點j。
對於y[j]<y[i]的節點,f[j][1]天然而然能夠轉移到f[i][0];
對於y[j]>y[i]的節點,i能夠向j進行轉移。
但是這樣就存在一個問題:並非全部的f[i][0]表示的折線都能合法地轉移到f[j][1]。
所以,咱們不得不枚舉k,當?y[i]>y[k]且x[k]>x[j]時才能轉移。
粗問題了!!!這不就n^3了嗎?
但當咱們再仔細研究這兩個條件時,發現:f[i][0]是全部知足y[k]<y[i]的f[k][1]之和。
那如何處理f[i][0],才能知足x[k]>x[j]呢?
發現x座標是有序的,那咱們倒序枚舉j不就好了嗎!!
很好的一道思惟題。。ip
#include<bits/stdc++.h> using namespace std; #define re register int #define F(x,y,z) for(re x=y;x<=z;x++) #define FOR(x,y,z) for(re x=y;x>=z;x--) typedef long long ll; #define I inline void #define IN inline int I read(int &res){ res=0;re g=1;register char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')g=-1; ch=getchar(); } while(isdigit(ch)){ res=(res<<3)+(res<<1)+(ch^48); ch=getchar(); } res*=g; } struct P{ int x,y; friend bool operator < (P a,P b){ return a.x==b.x?a.y<b.y:a.x<b.x; } }p[6060]; const int E=1e9+7; int n,m,f[6060][2],ans; int main(){ freopen("refract5.in","r",stdin); freopen("refract.out","w",stdout); read(n); F(i,1,n){ read(p[i].x);read(p[i].y); } sort(p+1,p+1+n); F(i,1,n){ f[i][0]=f[i][1]=1; FOR(j,i-1,1){ if(p[j].y>p[i].y)f[j][1]=(f[j][1]+f[i][0])%E; else f[i][0]=(f[i][0]+f[j][1])%E; } } ans=E-n; F(i,1,n){ ans=(ans+f[i][0])%E; ans=(ans+f[i][1])%E; } printf("%d",ans); return 0; }
paint.cpp/in/out
Time Limit: 1s
Memory Limit: 128MB
Description
小 G 的喜歡做畫, 尤爲喜歡僅使用黑白兩色做畫.
畫做能夠抽象成一個 r ×c 大小的 01 矩陣. 如今小 G 構思好了了他的
畫做, 準備動筆開始做畫. 初始時畫布是全白的, 他每一次下筆能夠將一個
四聯通的部分塗成黑色或白色.
你須要告訴他, 在給出的構思下, 他最少須要下筆多少次才能完成畫做.
Input Format
第一行兩個正整數 r, c.
接下來 r 行, 每行 c 個字符, 表示目標畫做.
Output Format
輸出一行一個正整數, 表示最少須要的下筆步數.
Sample Input
3 3
010
101
010
Sample Output
2
Constraints
• Subtask 1 (19pts): r × c ≤ 15.
• Subtask 2 (7pts): r = 1.
• Subtask 3 (25pts): r, c ≤ 30.
• Subtask 4 (49pts): r, c ≤ 50.get
不難證實猜到一個這樣的結論: 存在一種最優方案使得每次操做的區
域是上一次的子集且顏色與上一次相反.
考慮概括證實, 記 S 爲當前全部操做區域的並, T 爲接下來一步的操做
區域, 咱們有:it
#include<bits/stdc++.h> using namespace std; #define re register int #define F(x,y,z) for(re x=y;x<=z;x++) #define FOR(x,y,z) for(re x=y;x>=z;x--) typedef long long ll; #define I inline void #define IN inline int I read(int &res){ res=0;re g=1;register char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')g=-1; ch=getchar(); } while(isdigit(ch)){ res=(res<<3)+(res<<1)+(ch^48); ch=getchar(); } res*=g; } const int INF=1e9+7; char c[60][60]; int mx[5]={0,1,0,-1,0},my[5]={0,0,1,0,-1}; int n,m,X,Y,dis[60][60],ans; typedef pair<int,int>pii; #define mp(x,y) make_pair(x,y) deque<pii>q; IN B_1(int x,int y){ re res=0; memset(dis,-1,sizeof(dis)); dis[x][y]=0; q.push_back(mp(x,y)); while(!q.empty()){ x=q.front().first;y=q.front().second;q.pop_front(); if(c[x][y]=='1')res=max(res,dis[x][y]); F(i,1,4){ X=x+mx[i];Y=y+my[i]; if(X>=1&&X<=n&&Y>=1&&Y<=m&&dis[X][Y]==-1){ if(c[x][y]==c[X][Y]){ dis[X][Y]=dis[x][y]; q.push_front(mp(X,Y)); } else{ dis[X][Y]=dis[x][y]+1; q.push_back(mp(X,Y)); } } } } return res; } int main(){ read(n);read(m); F(i,1,n){ scanf("%s",c[i]+1); } ans=INF; F(i,1,n){ F(j,1,m){ ans=min(ans,B_1(i,j)); } } printf("%d",ans+1); return 0; }
本次模擬賽考了55+0+0。雖然考試時前兩題都想到了很是接近正解的思路, 但就是差那麼一點點。仍是要多多打怪作題,積攢經驗。