發表文章

目前顯示的是有「前綴和」標籤的文章

[TIOJ] 1134. 1.蓋房子問題

題目連結: http://tioj.infor.org/problems/1134 想了想覺得把1換成-1, 0換成1之後會有好事情,然後似乎可以做類似最大子矩陣的方式,但是我不知道該怎麼用。 被雷了之後才發現其實我只要把兩個問題合在一起就好了,一個是最大子矩陣,一個是某種找有多少大於零的序列的問題。首先我們可以先對一維用前綴和之後枚舉頂跟底,接著就變成一維的問題了,變成一維的問題後就是要問說對於所有大於零的序列中,最長是多少,作法也是考慮枚舉前綴和,每次只要查小於當前前綴和的所有鍵值中最小的值是多少,接著就把當前前綴和當做鍵值,現在的位置當作值插到某種資料結構就好了。 #include <bits/stdc++.h> using namespace std; #define ALL(x) begin(x), end(x) const int N = 200 + 5; const int INF = 1<<30; class LiSan{ private: vector<int> vv; public: inline void init(){vv.clear();} inline void insert(int x){vv.push_back(x);} inline void done(){ sort(ALL(vv)); vv.resize(distance(vv.begin(), unique(ALL(vv)))); } inline int size(){return vv.size();} inline int get(int x){ return distance(vv.begin(), lower_bound(ALL(vv), x)); } inline int inv_get(int x){return vv[x];} ...

[TIOJ] 1062. 用餐地點(Lunch)

題目連結: http://tioj.infor.org/problems/1062 這題題目好像有點怪,但還在可理解的範圍內,總之就是問你說給你網格內的一堆數,每個人移動都有1單位的cost,問你選哪個點讓大家都移動到他後的cost最小。 可以發現其實左右跟上下是可以分開的,因為他不能斜的走。所以就從左到右枚舉哪個點可以並從上到下枚舉哪個點可以,兩個混和在一起就好了。 #include <bits/stdc++.h> using namespace std; typedef long long lld; typedef pair<lld, int> PLI; #define FF first #define SS second const int N = 100 + 5; const lld INF = 1LL<<60; lld X[N], Y[N]; int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n, m; cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ int x; cin>>x; X[j]+=x; Y[i]+=x; } } PLI ansX={INF, 0}, ansY={INF, 0}; lld curX=0, curY=0; for(int i=1;i<=m;i++) curX+=X[i]*i; for(int i=1;i<=n;i++) curY+=Y[i]*i; for(int i=1;i<=m;i++) X[i]+=X[i-1]; for(int i=1;i<=n;i++) Y[i]+=Y[i-1]; f...

[TIOJ] 1991. 冰塊盒

題目連結: http://tioj.infor.org/problems/1991 大概看個一兩眼就會發現其實橫的跟直的可以分開,每個區塊都是獨立的(表示我選了這塊,我再選另一塊並不會影響前面那塊的值(某些奇怪的題目會有)),所以不難發現實作個二維的前綴和就好了,跟普通前綴和差不多,就輸出的時候再扣掉不要的部分就好了。 #include <bits/stdc++.h> using namespace std; const int N = 2000000 + 5; #define Hash(i, j) ((i)*(m+1)+(j)) bool mtx[N]; int preH[N], preZ[N]; int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n, m; cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>mtx[Hash(i, j)]; if(mtx[Hash(i, j)] and mtx[Hash(i, j-1)]) preH[Hash(i, j)]++; if(mtx[Hash(i, j)] and mtx[Hash(i-1, j)]) preZ[Hash(i, j)]++; preH[Hash(i, j)]+=preH[Hash(i, j-1)]; preZ[Hash(i, j)]+=preZ[Hash(i-1, j)]; } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ preH[Hash(i, j)]+=preH[Hash(i-1, j)]; preZ[Ha...