日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

蓝桥备赛第二周 前缀和

發布時間:2024/10/8 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝桥备赛第二周 前缀和 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前綴和與差分數組
    • [HNOI2003]激光炸彈
      • 前綴和解法(他又不變,,,前綴和就能搞定吧?)
        • 這種地方出現的錯誤(部分數據過不去)可能是少個等于之類的邊界問題
        • 2021-3-10復習,這里非常聰明的從1開始,到5001(輸入也+1),整個求和矩陣向右下方移一位,把a[0][x] a[x][0] 都設為0,這樣訪問a[i-1][j]的時候就都是0,不用特判
      • 線段樹+掃描線解法
    • Tallest Cow-----差分數組
      • 這個應該是線段樹了吧,不對,應該也不用?差分數組就行吧
      • 差分數組就行,兩個之間的-1,也就是【a+1】 -- 【b】++
      • 但我沒想明白a<=b的條件怎么用就過了?
      • 可能一個序列給兩遍,要去重
      • 標記數組有點大了,下次可以試試用map
    • 2021.3.10復習:///cows[0]=H 這里體現基數,之前cows數組代表身高差,另外cows[p]一定為0
    • IncDec Sequence
      • 我們最終的目標是將差分數組變成第一個位置是最終的數字,2~n都是0
      • 每次對[l,r]進行+1/-1,相當于在差分后的數組上對l進行+1/-1,然后對r+1進行-1/+1
      • 特殊的,如果r=n,那么就相當于對l進行了+1/-1!!!!!!!!!2021.3.10
      • 那么我們統計差分后的數組的2~n號位置上每個位置上的數
      • 令pos為所有正數的和,neg為所有負數的和的絕對值
      • 那么首先是pos和neg對消 可能會剩下
      • ~~剩下的有兩種選擇:自己消掉或者與1號位置對消~~
      • 看做求出原序列的差分之后,將 S[2...n] 全部變為0所需的最少的步數和可以使 S[1] 變為多少種不同的數。
      • 故第一問答案為max(pos,neg) 第二問答案為abs(pos-neg)+1
        • 注意點:1.最好還是建兩個數組,一個存原來的,一個存差分,不然容易出錯
        • 2.另外這道狗題要用longlong(淦歐)
      • 2021.3.10 所剩余的數有兩種選擇!!!!!!
        • 另外 b[2]到b[n]都變成0就可以了
      • 2021.4.17總結:
    • Best Cow Fences
      • 二分+類前綴和(這道題真的離譜到家了)
        • 另外這個題好像動規還是貪心里面那個一串數從左往右最大值!!!(check里面就是這個思路)
        • 二分枚舉平均值,驗證當前的平均值是不是區間最大
          • “先二分答案。接著對于每個候選答案,盡量在O(n)時間內驗證。”
      • [C++ 中的 inline 用法](https://www.runoob.com/w3cnote/cpp-inline-usage.html)
    • Cinema(離散化)
      • 離散化
        • 離散化的解法:
      • 排序
      • 我看一大堆離譜題解,這稀疏的用個map不就得了嘛
          • malloc動態開數組時需要賦初值(也可以用memset很快的),另外還發現了上面的問題(最后一組的M


前綴和與差分數組

原理與性質
https://www.cnblogs.com/mrpeng2333/p/11183654.html


[HNOI2003]激光炸彈

鏈接:https://ac.nowcoder.com/acm/problem/20032 來源:牛客網

一種新型的激光炸彈,可以摧毀一個邊長為R的正方形內的所有的目標。 現在地圖上有n(N ≤ 10000)個目標,用整數Xi,Yi(其值在[0,5000])表示目標在地圖上的位置,每個目標都有一個價值。 激光炸彈的投放是通過衛星定位的,但其有一個缺點,就是其爆破范圍,即那個邊長為R的正方形的邊必須和x,y軸平行。 若目標位于爆破正方形的邊上,該目標將不會被摧毀。 輸入描述: 輸入文件的第一行為正整數n和正整數R,接下來的n行每行有3個正整數,分別表示 xi,yi ,vi 。 輸出描述: 輸出文件僅有一個正整數,表示一顆炸彈最多能炸掉地圖上總價值為多少的目標(結果不會超過32767)。 示例1 輸入 復制 2 1 0 0 1 1 1 1 輸出 復制 1


前綴和解法(他又不變,,,前綴和就能搞定吧?)

先錄入價值,然后a[i][j]表示以(1,1)為左上角,(i,j)為右下角所構成的矩陣的價值和(二維前綴和矩陣)
這樣b[i+m][j+m]-b[i+m][j]-b[i][j+m]+b[i][j]直接減就求出R內的值(其實就是暴力)
https://blog.csdn.net/weixin_44382711/article/details/112742528

這種地方出現的錯誤(部分數據過不去)可能是少個等于之類的邊界問題

2021-3-10復習,這里非常聰明的從1開始,到5001(輸入也+1),整個求和矩陣向右下方移一位,把a[0][x] a[x][0] 都設為0,這樣訪問a[i-1][j]的時候就都是0,不用特判

#include <iostream> #include<bits/stdc++.h> using namespace std; #define maxn 10005 int a[maxn][maxn]={0}; int main() {int n,R;cin>>n>>R;int xi,yi,vi;for(int i=0;i<n;i++){cin>>xi>>yi>>vi;a[xi+1][yi+1]=vi;}for(int i=1;i<=5000;i++){for(int j=1;j<=5000;j++)///遍歷每一個點,計算以(1,1)為左上角,(i,j)為右下角的價值和{a[i][j]=a[i][j-1]+a[i-1][j]-a[i-1][j-1]+a[i][j];}}int ans=0;for(int i=0;i<=5000-R;i++)///這里要寫等與號///而且不能改成1!!!!!!{for(int j=0;j<=5000-R;j++){ans=max(ans,a[i+R][j+R]-a[i+R][j]-a[i][j+R]+a[i][j]);///反過來的話:ans=max,,,,,, a[i][j]-a[i][j-R]-a[i-R][j]+a[i-R][j-R];}}cout<<ans;return 0; }

線段樹+掃描線解法

https://blog.csdn.net/weixin_44382711/article/details/112738169
https://blog.csdn.net/icefox_zhx/article/details/78077506


Tallest Cow-----差分數組

鏈接:https://ac.nowcoder.com/acm/problem/25044 來源:牛客網

FJ's N (1 ≤ N ≤ 10,000) cows conveniently indexed 1..N are standing in a line. Each cow has a positive integer height (which is a bit of secret). You are told only the height H (1 ≤ H ≤ 1,000,000) of the tallest cow along with the index I of that cow. FJ has made a list of R (0 ≤ R ≤ 10,000) lines of the form "cow 17 sees cow 34". This means that cow 34 is at least as tall as cow 17, and that every cow between 17 and 34 has a height that is strictly smaller than that of cow 17. For each cow from 1..N, determine its maximum possible height, such that all of the information given is still correct. It is guaranteed that it is possible to satisfy all the constraints. ---------------------------------------------------------------------------------------------- N(1≤N≤10000)頭1..N奶牛排成一行。每頭牛都有一個正整數的高度(這有點秘密)。 你只知道最高奶牛的身高H(1≤H≤1000000)以及該奶牛的位置I。 FJ列出了R(0≤R≤10000)行,形式為“17牛見34牛”。 這意味著34號奶牛至少和17號奶牛一樣高,1734號之間的每頭奶牛的身高都比17號奶牛要小。 對于從1..N開始的每頭母牛,確定其最大可能高度,以便給出的所有信息仍然正確。可以保證滿足所有的約束條件。 輸入描述: Line 1: Four space-separated integers: N, I, H and R Lines 2..R+1: Two distinct space-separated integers A and B (1 ≤ A, B ≤ N), indicating that cow A can see cow B. 輸出描述: Lines 1..N: Line i contains the maximum possible height of cow i. 示例1 輸入 復制 9 3 5 5 1 3 5 3 4 3 3 7 9 8 輸出 復制 5 4 5 3 4 4 5 5 5


這個應該是線段樹了吧,不對,應該也不用?差分數組就行吧

差分數組就行,兩個之間的-1,也就是【a+1】 – 【b】++

但我沒想明白a<=b的條件怎么用就過了?

可能一個序列給兩遍,要去重

標記數組有點大了,下次可以試試用map

#include <iostream> #include<bits/stdc++.h> using namespace std; #define maxn 10005 int cows[maxn]={0}; ///這個憨批題可能一道條件出兩遍 bool judge[maxn][maxn];///默認0 int main() {int N,I,H,R;cin>>N>>I>>H>>R;cows[0]=H;///每個代表與前面的牛的身高高多少,可以負數///不用管N cows[I],他肯定不會處在兩端點之間,最后他的和肯定為0;int a,b;while(R--){cin>>a>>b;if(a>b)swap(a,b);if(judge[a][b]==true)continue;cows[a+1]--;cows[b]++;judge[a][b]=true;}for(int i=1;i<=N;i++){cows[i]+=cows[i-1];///cows[0]=H 這里體現基數,之前cows數組代表身高差,另外cows[p]一定為0}for(int i=1;i<=N;i++){cout<<cows[i]<<endl;}return 0; }

2021.3.10復習:///cows[0]=H 這里體現基數,之前cows數組代表身高差,另外cows[p]一定為0

///每個代表與前面的牛的身高高多少,可以負數
///不用管N cows[I],他肯定不會處在兩端點之間,最后他的和肯定為0;
注意一個序列給兩遍,要去重的情況!!!!!!!!!!!


IncDec Sequence

鏈接:https://ac.nowcoder.com/acm/problem/50929
來源:牛客網

給定一個長度為 n(n \leq 10^5 )(n≤10 5) 的數列{a_1,a_2,,a_n}a 1 ? ,a 2 ? ,,a n ? ,每次可以選擇一個區間 [l,r],使下標在這個區間內的數都加一或者都減一。 求至少需要多少次操作才能使數列中的所有數都一樣,并求出在保證最少次數的前提下,最終得到的數列可能有多少種。 輸入描述: 第一行一個正整數n。 接下來n行,每行一個整數,第i+1行的整數表示a_ia i ? 。 輸出描述: 第一行輸出最少操作次數。 第二行輸出最終能得到多少種結果。 示例1 輸入 復制 4 1 1 2 2 輸出 復制 1 2 備注: 對于100%的數據,n=1000000 \leq ai \lt 21474836480≤ai<2147483648

https://www.cnblogs.com/719666a/p/10089194.html
https://www.luogu.com.cn/blog/TheShadow/p4552-poetize6-incdec-sequence-you-qu-di-ci-fen-ti-xie

我們最終的目標是將差分數組變成第一個位置是最終的數字,2~n都是0

每次對[l,r]進行+1/-1,相當于在差分后的數組上對l進行+1/-1,然后對r+1進行-1/+1

特殊的,如果r=n,那么就相當于對l進行了+1/-1!!!!!!!!!2021.3.10

那么我們統計差分后的數組的2~n號位置上每個位置上的數

令pos為所有正數的和,neg為所有負數的和的絕對值

那么首先是pos和neg對消 可能會剩下

剩下的有兩種選擇:自己消掉或者與1號位置對消

看做求出原序列的差分之后,將 S[2…n] 全部變為0所需的最少的步數和可以使 S[1] 變為多少種不同的數。

故第一問答案為max(pos,neg) 第二問答案為abs(pos-neg)+1

注意點:1.最好還是建兩個數組,一個存原來的,一個存差分,不然容易出錯

2.另外這道狗題要用longlong(淦歐)

2021.3.10 所剩余的數有兩種選擇!!!

比如是正數:則是這個數之后的數都比這個數之前的大(假設前后都是0)
與S[1]配對:使這個數之前的數增加,也就是s[1]+1 s[x]-1
與S[n+1]配對:使這個數之后的數減小(都減一),也就是s[n+1]+1 s[x]-1(s[n+1]應該是與最后一個數的差值,為負數)
負數的話就相反

另外 b[2]到b[n]都變成0就可以了

2021.4.17總結:

eg:
22225555
00003000
這樣結果可以是全2,全3,全4,全5 (左邊往上+或者右遍往下減)
也就是3+1種


Best Cow Fences

大意是說,給你一個正整數序列,找出一個區間使得平均值最大,要求該區間的長度大于等于F。

二分+類前綴和(這道題真的離譜到家了)

另外這個題好像動規還是貪心里面那個一串數從左往右最大值!!!(check里面就是這個思路)

二分枚舉平均值,驗證當前的平均值是不是區間最大

“先二分答案。接著對于每個候選答案,盡量在O(n)時間內驗證。”


https://www.cnblogs.com/liucongyu/p/6357610.html
http://www.cppblog.com/varg-vikernes/archive/2010/03/02/108737.aspx
http://www.voidcn.com/article/p-dgfakbof-bxn.html
https://blog.csdn.net/qq_42500298/article/details/82915017(這個代碼好)

C++ 中的 inline 用法

解決一些頻繁調用的小函數大量消耗棧空間(棧內存)的問題,
inline 只適合涵數體內代碼簡單的涵數使用,不能包含復雜的結構控制語句例如 while、switch,并且不能內聯函數本身不能是直接遞歸函數(即,自己內部還調用自己的函數)。
它如果認為函數不復雜,能在調用點展開,就會真正內聯,并不是說聲明了內聯就會內聯,聲明內聯只是一個建議而已。

#include <iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 100005 int N,F; double a[maxn],sum[maxn]; double rmaxsum[maxn]; double le,ri,mid; bool checker(double val) { // for(int i=N;i>=1;i--) // { // rmaxsum[i]=max(a[i]-val,rmaxsum[i+1]+a[i]-val); // /// 每個數都減val 看看右側的選不選 // ///定義rmaxsum[i]為以i為起點,向右延長的最大和。 // ///如果rmax[i+1]>=0,那么rmax[i]=rmax[i+1]+a[i]。 // ///若rmax[i+1]<0,那么不如扔掉i+1及其之后的數字,故此時rmax[i]=a[i]。 // /// !!! 左側的最大和肯定比右側可能性大(包含),所以從右向左(遞推) // }double sum1=sum[F-1]-(F-1)*val;for(int i=F;i<=N;i++)///從左往右看,求所有可能的區間{double sum2=sum[i]-sum[i-F]-F*val;sum1=sum1+a[i]-val;///向右生長的要還是不要a[i]sum1=max(sum1,sum2);///是直接往右查F個大,還是接著之前的那個已經查了一部分的大if(sum1>-1e-5){///i+F-1到i-1的和///去掉當前驗證的平均值的和(F長)大于0///說明這個數列存在平均在比這個還大的return true;}}return false;}int main() {cin>>N>>F;le=maxn;ri=0;///牛的數量肯定大于等于0for(int i=1;i<=N;i++){cin>>a[i];sum[i]=sum[i-1]+a[i];///b[i]是和,兩個之間的一減就出來ri=max(ri,a[i]);le=min(le,a[i]);}double eps=1e-5;///誤差while(le<ri-eps)///標準二分{mid=(ri+le)/2;if(checker(mid)){le=mid;}else{ri=mid;}}cout<<int(ri*1000)<<endl;return 0; }

Cinema(離散化)

鏈接:https://ac.nowcoder.com/acm/problem/50936
來源:牛客網

大意: 有 n 個人,每人會且僅會一種語言. (n ≤ 2e5) 語言有各自的編號(≤ 1e9) 這些人去看電影,一共有 m 種電影. (m ≤ 2e5) 每個電影的聲音與字幕語言都不一樣. 若有人的語言與聲音語言一樣,則稱這個人很高興♂. 若有人的語言與字幕語言一樣,則稱這個人比較高興. 現讓你選擇一場電影,使得此電影中,很高興的人最多,在此條件下,再使比較高興的人最多.Moscow is hosting a major international conference, which is attended by nscientists from different countries. Each of the scientists knows exactly one language. For convenience, we enumerate all languages of the world with integers from 1 to 10^910 9. In the evening after the conference, all n scientists decided to go to the cinema. There are m movies in the cinema they came to. Each of the movies is characterized by two distinct numbers — the index of audio language and the index of subtitles language. The scientist, who came to the movie, will be very pleased if he knows the audio language of the movie, will be almost satisfied if he knows the language of subtitles and will be not satisfied if he does not know neither one nor the other (note that the audio language and the subtitles language for each movie are always different). Scientists decided to go together to the same movie. You have to help them choose the movie, such that the number of very pleased scientists is maximum possible. If there are several such movies, select among them one that will maximize the number of almost satisfied scientists.輸入描述: The first line of the input contains a positive integer n (1?\leq n \leq 200?000)(1?≤n≤200?000) — the number of scientists. The second line contains n positive integers a_1,a_2,?\dots ,a_na 1 ? ,a 2 ? ,?…,a n ? (1?≤a_i ≤?10^9)(1?≤a i ? ≤?10 9), where aiis the index of a language, which the i-th scientist knows. The third line contains a positive integer m(1\leq m\leq?200?000)(1≤m≤?200?000)— the number of movies in the cinema. The fourth line contains m positive integers b_1,b_2,\dots,b_mb 1 ? ,b 2 ? ,,b m ? (1?≤b_j ≤?10^9)(1?≤b j ? ≤?10 9), where bjis the index of the audio language of the j-th movie. The fifth line contains m positive integers c_1,c_2,?\dots,c_mc 1 ? ,c 2 ? ,?…,c m ? (1?≤c_j ≤?10^9)(1?≤c j ? ≤?10 9), where cj is the index of subtitles language of the j-th movie. It is guaranteed that audio languages and subtitles language are different for each movie, that is b_j \not= c_jb j ?  ? =c j ? . 輸出描述: Print the single integer — the index of a movie to which scientists should go. After viewing this movie the number of very pleased scientists should be maximum possible. If in the cinema there are several such movies, you need to choose among them one, after viewing which there will be the maximum possible number of almost satisfied scientists. If there are several possible answers print any of them. 示例1 輸入 復制 3 2 3 2 2 3 2 2 3 輸出 復制 2 示例2 輸入 復制 6 6 3 1 1 3 7 5 1 2 3 4 5 2 3 4 5 1 輸出 復制 1

離散化

離散化
https://blog.csdn.net/s_999999/article/details/99080549
離散化:兩種離散化方式詳解
https://blog.csdn.net/weixin_43061009/article/details/82083983

離散化的解法:

https://blog.csdn.net/weixin_45719073/article/details/104267772
用abc三個數組來存編號,然后用d來去重,d里面存著所有的index,d對應著num 這樣查一個就可以在d里面查index(語言編號)對應的i(該語言對應的數組編號),然后上num++ – 查詢人數,另外再給d用排序,這樣查詢的時候就能二分了

排序

我看一大堆離譜題解,這稀疏的用個map不就得了嘛

用map存語言,用結構體數組存電影(聲音,字幕的語言,然后分別上map里查對應的人數,然后遍歷一遍查最大值(音頻更大直接換,音頻相同時查字幕是不是更大))

#include <iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 200005 //int scien[maxn]; int lan[maxn]; struct movie{int aud,sub;///聲音語言和字幕語言int a,b;///此音頻母語人數,此字幕語言人數 }mov[maxn]; map<int,int>langer;int main() {int n;cin>>n;int sci;for(int i=1;i<=n;i++){cin>>sci;langer[sci]++;}int m;cin>>m;for(int i=1;i<=m;i++){cin>>mov[i].aud;}for(int i=1;i<=m;i++){cin>>mov[i].sub;}movie buf;buf.a=buf.b=0;int besti=0;for(int i=1;i<=m;i++){if(langer[mov[i].aud])///存在音頻{mov[i].a+=langer[mov[i].aud];}if(langer[mov[i].sub])///存在音頻{mov[i].b+=langer[mov[i].sub];}if(mov[i].a>buf.a){buf=mov[i];besti=i;}else if(mov[i].a==buf.a&&mov[i].b>buf.b)///第一條件相同,比較第二條件{buf=mov[i];besti=i;///母語index}}cout<<besti<<endl;return 0; }

v#### 小改進,加了動態開數組

malloc動態開數組時需要賦初值(也可以用memset很快的),另外還發現了上面的問題(最后一組的M<N),

這句話的m寫成n了

for(int i=1;i<=m;i++){if(langer[mov[i].aud])///存在音頻{mov[i].a+=langer[mov[i].aud];}if(langer[mov[i] #include <iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 200005 //int scien[maxn]; int lan[maxn]; struct movie{int aud,sub;///聲音語言和字幕語言int a,b;///此音頻母語人數,此字幕語言人數 }; map<int,int>langer;int main() {int n;cin>>n;int sci;for(int i=1;i<=n;i++){cin>>sci;langer[sci]++;}int m;cin>>m;movie *mov=(movie*)malloc(sizeof(movie)*(m+10));memset(mov,0,sizeof(movie)*(m+10));for(int i=1;i<=m;i++){cin>>mov[i].aud;//mov[i].a=mov[i].b=0;}for(int i=1;i<=m;i++){cin>>mov[i].sub;}movie buf;buf.a=buf.b=0;int besti=0;for(int i=1;i<=m;i++){if(langer[mov[i].aud])///存在音頻{mov[i].a+=langer[mov[i].aud];}if(langer[mov[i].sub])///存在音頻{mov[i].b+=langer[mov[i].sub];}if(mov[i].a>buf.a){buf=mov[i];besti=i;}else if(mov[i].a==buf.a&&mov[i].b>buf.b)///第一條件相同,比較第二條件{buf=mov[i];besti=i;///母語index}}cout<<besti<<endl;return 0; }
不對啊,應該占的內存小了啊,咋還大了,我人傻了


貨倉選址

鏈接:https://ac.nowcoder.com/acm/problem/50937 來源:牛客網題目描述 在一條數軸上有N家商店,它們的坐標分別為 A[1]~A[N]。現在需要在數軸上建立一家貨倉,每天清晨,從貨倉到每家商店都要運送一車商品。為了提高效率,求把貨倉建在何處,可以使得貨倉到每家商店的距離之和最小。 輸入描述: 第一行一個整數N,第二行N個整數A[1]~A[N]。 輸出描述: 一個整數,表示距離之和的最小值。 示例1 輸入 復制 4 6 2 9 1 輸出 復制 12 備注: 對于100%的數據:N\leq 100000N≤100000, A[i]\leq 1000000A[i]1000000

這題我第一眼都傻了,上來就是廣搜+動歸ptsd,說好的早睡呢

但其實就是當處于中間兩個數之間的時候,那么往左移和往右移并不影響總距離(一半全體+1另一半全體-1),而正好中間就不能動了,這也是要的是個距離和的值的原因(坐標不唯一)

也就是排個序直接求中位數(這題真的是按難度排序嘛)

細節:如果商店數為偶數的話,中點有兩個商店,此時在這兩個商店之間任選一點都可,即a[n/2]<=k<=a[n/2+1],因為除這兩個商店外左右兩邊的商店數是相等的(即k向右移總距離加減數相等),而這兩個商店到k的距離和又是定值,所以不影響答案,我們可以直接選擇a[n/2]。
#include <iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 100005 int a[maxn]; int main() {int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}sort(a+1,a+n+1);int mid=n/2;int sum=0;for(int i=1;i<=n;i++){sum+=abs(a[i]-a[mid]);}cout<<sum;return 0; }
另:明明是一樣的代碼為啥我的內存是人家一倍,,,,,,,

七夕祭P32

鏈接:https://ac.nowcoder.com/acm/problem/50939
來源:牛客網

七夕節因牛郎織女的傳說而被扣上了「情人節」的帽子。于是TYVJ今年舉辦了一次線下七夕祭。Vani同學今年成功邀請到了cl同學陪他來共度七夕,于是他們決定去TYVJ七夕祭游玩。描述 TYVJ七夕祭和11區的夏祭的形式很像。矩形的祭典會場由N排M列共計N×M個攤點組成。雖然攤點種類繁多,不過cl只對其中的一部分攤點感興趣,比如章魚燒、蘋果糖、棉花糖、射的屋……什么的。Vani預先聯系了七夕祭的負責人zhq,希望能夠通過恰當地布置會場,使得各行中cl感興趣的攤點數一樣多,并且各列中cl感興趣的攤點數也一樣多。不過zhq告訴Vani,攤點已經隨意布置完畢了,如果想滿足cl的要求,唯一的調整方式就是交換兩個相鄰的攤點。兩個攤點相鄰,當且僅當他們處在同一行或者同一列的相鄰位置上。由于zhq率領的TYVJ開發小組成功地扭曲了空間,每一行或每一列的第一個位置和最后一個位置也算作相鄰。現在Vani想知道他的兩個要求最多能滿足多少個。在此前提下,至少需要交換多少次攤點。輸入描述: 第一行包含三個整數N和M和T。T表示cl對多少個攤點感興趣。 接下來T行,每行兩個整數x, y,表示cl對處在第x行第y列的攤點感興趣。 輸出描述: 首先輸出一個字符串。如果能滿足Vani的全部兩個要求,輸出both;如果通過調整只能使得各行中cl感興趣的攤點數一樣多,輸出row;如果只能使各列中cl感興趣的攤點數一樣多,輸出column;如果均不能滿足,輸出impossible。 如果輸出的字符串不是impossible, 接下來輸出最小交換次數,與字符串之間用一個空格隔開。 示例1 輸入 復制 2 3 4 1 3 2 1 2 2 2 3 輸出 復制 row 1 示例2 輸入 復制 3 3 3 1 3 2 2 2 3 輸出 復制 both 2

根據前幾道的經驗,我估計這是個數學題

交換上下和交換左右分別只影響行和列,所以可以分離

題解+均分紙牌題解
https://www.cnblogs.com/suansuan918106840226/p/12274711.html

非常有意思 原題=2個環形紙牌=2個(均分紙牌+貨倉)

#include <iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; int N,M,T; #define maxn 100005 int a[maxn],b[maxn],sum[maxn]; ///ab為坐標,同時也是兩個需要均分的數組 int main() {cin>>N>>M>>T;int x,y;for(int i=1;i<=T;i++){cin>>x>>y;a[x]++;b[y]++;}if(T%N!=0&&T%M!=0)///無法均分紙牌{cout<<"impossible";return 0;}for(int i=1;i<=N;i++){a[i]-=T/N;///等效的,這樣可以記錄需要傳遞的牌數}for(int i=1;i<=M;i++){b[i]-=T/M;}ll ans=0;if(T%N==0){///for(int i=1;i<=N;i++){sum[i]=sum[i-1]+a[i];///前綴和}sort(sum+1,sum+1+N);int mid=(N+1)/2;///貨倉選址for(int i=1;i<=N;i++){ans+=abs(sum[i]-sum[mid]);}}if(T%M==0){///for(int i=1;i<=M;i++){sum[i]=sum[i-1]+b[i];///前綴和}sort(sum+1,sum+1+M);int mid=(M+1)/2;///貨倉選址for(int i=1;i<=M;i++){ans+=abs(sum[i]-sum[mid]);}}if(T%M==0&&T%N==0)printf("both ");else if(T%M==0)printf("column ");else printf("row ");cout<<ans;return 0; }

Running Median(還有別的解法,有空看看)

依次給出n個數字,每輸入一個奇數則輸出即時中位數。(共有(n+1)/2個)

對頂堆,即用兩個堆,一個大根堆一個小根堆。每次比較兩個堆的堆頂,如果不相等就交換堆頂,否則堆頂即為所要求的中位數。

#include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<cctype>inline void read(int &x) {char c=getchar(); int f=1;x=0;while(!isdigit(c)) {if (c=='-') f=-1;c=getchar();}while(isdigit(c)) {x=x*10+c-48;c=getchar();}x*=f; return; } std::priority_queue <int> lq,sq; //lq大根堆,sq小根堆 int main() {int n,t,x,a,b,cnt;read(t);while(t--){read(cnt); read(n);while(lq.size()) lq.pop();while(sq.size()) sq.pop();printf("%d %d\n",cnt,(n+1)/2);for(int i=1;i<=n;i++){read(x);lq.push(x),sq.push(-x);if(i%2==0) continue;while(lq.top()!=-sq.top()){a=lq.top();lq.pop();b=-sq.top();sq.pop();sq.push(-a);lq.push(b);}printf("%d ",lq.top());if(((i+1)/2)%10 == 0) puts("");else if((n%2==1&&i==n)||(n%2==0&&i==n-1))puts("");}}return 0; }

逆序對

用歸并排序計算逆序對個數
l到r,

短路運算符,所以沒加括號

!!歸并排序逆序對模板(就記這個吧,準些)

bits/stdc++.h> using namespace std; const int N=501000; #define ll long long ll n,m,i,j,k,a[N],b[N],cnt; void merge(ll a[],ll l,ll r) {if (r-l<1)///等價于l==rreturn ;ll mid=(l+r)/2;merge(a,l,mid);merge(a,mid+1,r);ll i=l,j=mid+1;for (ll k=l;k<=r;k++){if (j>r || i<=mid && a[i]<=a[j])///這里有個等號b[k]=a[i++];else{cnt+=mid-i+1;b[k]=a[j++];}}for (ll k=l;k<=r;k++)a[k]=b[k]; } int main() {ios::sync_with_stdio(false);while(cin>>n && n){for (i=1;i<=n;i++)cin>>a[i];cnt=0;merge(a,1,n);///用的時候直接輸入1到n(a[n]里也有數)cout<<cnt<<endl;}return 0; }

Ultra-QuickSort


就是冒泡排序次數(每找到一對顛倒逆序對,都要交換一次,逆序對個數-1),也是逆序對個數

#include <iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 500005 int cnt=0; int a[maxn],b[maxn];void my_merge(int l,int mid,int r) {int i=l,j=mid+1;for(int k=l;k<=r;k++){if(j>r||i<=mid&&a[i]<a[j]){b[k]=a[i++];}else{b[k]=a[j++];cnt+=mid-i+1;///a[j]較小,則a[i~mid]都比a[j]大(因為歸并嘛,排好之后a[j]在他們前面)}}for(int k=l;k<=r;k++){a[k]=b[k];}} void s2(int l,int r) {if(l==r)return ;int mid=(l+r)/2;s2(l,mid);s2(mid+1,r);my_merge(l,mid,r); } int main() {int buf;int n=0;///inputwhile(cin>>n){if(n==0){break;}cnt=0;for(int i=0;i<n;i++){cin>>a[i];}s2(0,n-1);cout<<cnt<<endl;}return 0; }

奇數碼游戲

他只問行不行

空格左右移動時,逆序對個數肯定不變(因為就是正常移嘛)

上下移動時,那就是移動過去,也就是一個數和n-1個數交換位置,奇偶不變

橫向展開成一位序列,計算逆序對個數

第一遍的代碼,這個很離譜,不知道為什么會隨機的無法輸入?一會70%一會10%,純看運氣

#include <iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 500*500+5 int n; int a[maxn],b[maxn],a2[maxn]; ///int cnt1=0; ///int cnt2=0;void my_merge(int l,int mid,int r,int *yuan,int *buf) {int i=l,j=mid+1;for(int k=l;k<=r;k++){if(j>r||i<=mid&&yuan[i]<yuan[j])///三個條件一次寫錯,我真的是{buf[k]=yuan[i++];}else{buf[k]=yuan[j++];///cnt1++;///寫錯了yuan[500*500+3]+=mid-i+1;}}for(int k=l;k<=r;k++){yuan[k]=buf[k];} }void s2(int l,int r,int *yuan,int *buf) {if(l==r){return ;}int mid=(l+r)/2;s2(l,mid,yuan,buf);s2(mid+1,r,yuan,buf);my_merge(l,mid,r,yuan,buf);}int main() {int n;while(cin>>n){if(n==1){cin>>a[0];cin>>a2[0];cout<<"TAK"<<endl;continue;}// cout<<"main1"<<endl;int buf;for(int i=0;i<n*n-1;i++){cin>>buf;if(buf==0){i--;continue;}else{a[i]=buf;}}for(int i=0;i<n*n-1;i++){cin>>buf;if(buf==0){i--;continue;}else{a2[i]=buf;}}//cout<<"main2"<<endl;a[500*500+3]=0;a2[500*500+3]=0;s2(0,n*n-1-1,a,b);s2(0,n*n-1-1,a2,b);int ji1=a[500*500+3]%2;int ji2=a2[500*500+3]%2;// cout<<"main3"<<endl;if(ji1==ji2){cout<<"TAK"<<endl;}else{cout<<"NIE"<<endl;}}return 0; }

第二遍的代碼

如果說總是要多輸入幾次才能行,可以在每個輸入下面寫輸出,看看是不是循環輸入次數算錯了

目前出現的憨批錯誤

1.cnt+=mid-i+1;沒寫+號
2.a[m++]=buf;多寫個等號結果全沒輸入進去
3.

#include <iostream> #include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 505*505 ll cnt; int a[maxn],b[maxn];void my_merge(int l,int mid,int r) {int i=l,j=mid+1;for(int k=l;k<=r;k++){if(j>r||i<=mid&&a[i]<=a[j]){b[k]=a[i++];}else{b[k]=a[j++];cnt+=mid-i+1;///a[j]較小,則a[i~mid]都比a[j]大(因為歸并嘛,排好之后a[j]在他們前面)}}//cout<<"*";for(int k=l;k<=r;k++){a[k]=b[k];}} void s2(int l,int r) {//cout<<"#";if(r-l<1)return ;int mid=(l+r)/2;s2(l,mid);s2(mid+1,r);my_merge(l,mid,r); } int main() { // ios::sync_with_stdio(0); // cin.tie(0); // cout.tie(0);int buf;int n;///inputwhile(cin>>n){if(n==1){cin>>buf;cin>>buf;cout<<"TAK"<<endl;}memset(a,0,sizeof(a));memset(b,0,sizeof(b));int m=0;for(int i=0;i<n*n;i++){cin>>buf;if(buf==0){continue;}a[m++]=buf;}ll ans1;cnt=0;s2(0,n*n-1);ans1=cnt;memset(a,0,sizeof(a));memset(b,0,sizeof(b));ll ans2;m=0;for(int i=0;i<n*n;i++){cin>>buf;if(buf==0){continue;}a[m++]=buf;}// // for(int i=0;i<n*n;i++) // { // cout<<a[i]<<" "; // }//cnt=0;s2(0,n*n-1);ans2=cnt;if((ans1&1)==(ans2&1)){cout<<"TAK"<<endl;}else{cout<<"NIE"<<endl;}}return 0; }

總結

以上是生活随笔為你收集整理的蓝桥备赛第二周 前缀和的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。