Problem A Magic Pairs
水体一枚,其实就是求1-n-1的和。用long long 就行。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #define LEN 101000 10 #define INF 0x7fffffff 11 #define ll long long 12 13 using namespace std; 14 15 int n, num[LEN]; 16 17 int main() 18 { 19 // freopen("in.txt", "r", stdin); 20 21 int T; 22 scanf("%d", &T); 23 while(T--){ 24 scanf("%d", &n); 25 for(int i=0; i<n; i++){ 26 scanf("%d", &num[i]); 27 } 28 ll ans = 0; 29 for(int i=n-1; i>0; i--){ 30 ans+=i; 31 } 32 cout << ans << endl; 33 } 34 return 0; 35 }
Problem B Chef and Codes
字符串操作。有中文题就不说意思了。
有一点比较坑就是原来是大写的字母转换后输出来也必须也是大写的。其他都ok。
代码如下:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #define LEN 101000 6 7 using namespace std; 8 9 struct Z{ 10 int pos, num; 11 }z[50]; 12 13 bool cmp(Z a, Z b){ 14 if(a.num!=b.num) return a.num<b.num; 15 else return a.pos<b.pos; 16 } 17 18 int main() 19 { 20 // freopen("in.txt", "r", stdin); 21 22 char str[LEN], dir[50], hash[50], flag[LEN]; 23 int T; 24 scanf("%d", &T);getchar(); 25 while(T--){ 26 memset(z, 0, sizeof z); 27 memset(flag, 0, sizeof flag); 28 for(int i=0; i<26; i++){ 29 z[i].pos = i; 30 dir[i] = getchar(); 31 } 32 getchar(); 33 gets(str); 34 for(int i=0; str[i]!=0; i++){ 35 if(str[i]>='A' && str[i]<='Z'){ 36 str[i] = str[i]-'A'+'a'; 37 flag[i] = 1; 38 } 39 if(str[i]>='a' && str[i]<='z'){ 40 z[str[i]-'a'].num++; 41 } 42 } 43 sort(z, z+26, cmp); 44 for(int i=0; i<26; i++){ 45 hash[z[i].pos] = dir[i]; 46 } 47 hash[26] = 0; 48 for(int i=0; str[i]!=0; i++){ 49 if(str[i]>='a' && str[i]<='z'){ 50 char cc = hash[str[i]-'a']; 51 if(flag[i])cc = cc-'a'+'A'; 52 putchar(cc); 53 } 54 else 55 putchar(str[i]); 56 } 57 putchar(' '); 58 } 59 return 0; 60 }
Problem E Funny Marbles
线段树点更新,然后区间查询。直接用模版改一下然后就a掉了。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <string.h> 4 #include <algorithm> 5 #define ll long long 6 7 using namespace std; 8 9 const int N = 1010000, MAX = 4*N; 10 ll BSTree[MAX]; 11 12 void Update(int l ,int r, int rt, int t, int data) 13 { 14 if(l==r && l==t){BSTree[rt] += data; return ;} 15 int mid = (l+r)>>1; 16 if(t<=mid) Update(l, mid, rt<<1,t,data); 17 if(t>mid)Update(mid+1 ,r, rt<<1|1, t, data); 18 BSTree[rt] = BSTree[rt<<1]+BSTree[rt<<1|1]; 19 } 20 21 ll Query(int l, int r, int rt, int tl, int tr) 22 { 23 if(l==tl && r == tr)return BSTree[rt]; 24 int mid = (l+r)>>1; 25 if(tr<=mid)return Query(l, mid, rt<<1, tl, tr); 26 if(tl>mid)return Query(mid+1, r, rt<<1|1, tl, tr); 27 return Query(l, mid, rt<<1, tl, mid)+Query(mid+1, r, rt<<1|1, mid+1, tr); 28 } 29 30 int main() 31 { 32 // freopen("in.txt", "r", stdin); 33 34 int n, q; 35 while(scanf("%d%d", &n, &q)!=EOF){ 36 memset(BSTree, 0, sizeof(BSTree)); 37 for(int i=1; i<=n; i++){ 38 int temp; 39 scanf("%d", &temp); 40 Update(1,N,1,i,temp); 41 } 42 for(int i=0; i<q; i++){ 43 int a, b;char c; 44 scanf("%s%d%d", &c, &a, &b); 45 if(c=='S'){ 46 printf("%lld ", Query(1,N,1,a+1,b+1)); 47 } 48 else if(c=='G'){ 49 Update(1,N,1,a+1,b); 50 } 51 else { 52 Update(1,N,1,a+1,-b); 53 } 54 } 55 } 56 return 0; 57 }
Problem H Rectangular Queries
水题一枚,直接统计从(1,1)-(i,j)中含有1-10的数字的个数,然后对于每次查询通过枚举每个数字有没有答案来确定答案。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <utility> 7 #include <vector> 8 #include <queue> 9 #include <stack> 10 #define INF 0x7fffffff 11 #define LEN 310 12 13 using namespace std; 14 15 int n, Map[LEN][LEN], dp[LEN][LEN][12]; 16 int x1, x2, y1, y2; 17 18 void init() 19 { 20 memset(dp, 0, sizeof dp); 21 for(int i=1; i<=n; i++){ 22 for(int j=1; j<=n; j++){ 23 for(int k=1; k<=10; k++){ 24 dp[i][j][k] = dp[i-1][j][k]+dp[i][j-1][k]-dp[i-1][j-1][k]; 25 } 26 dp[i][j][Map[i][j]]++; 27 } 28 } 29 } 30 31 int main() 32 { 33 // freopen("in.txt", "r", stdin); 34 35 while(scanf("%d", &n)!=EOF){ 36 for(int i=1; i<=n; i++){ 37 for(int j=1; j<=n; j++){ 38 scanf("%d", &Map[i][j]); 39 } 40 } 41 init(); 42 int q; 43 scanf("%d", &q); 44 for(int i=0; i<q; i++){ 45 scanf("%d%d%d%d", &x1, &y1, &x2, &y2); 46 int ans = 0; 47 for(int k=1; k<=10; k++){ 48 if(dp[x2][y2][k]-dp[x2][y1-1][k]-dp[x1-1][y2][k]+dp[x1-1][y1-1][k]) 49 ans++; 50 } 51 printf("%d ", ans); 52 } 53 } 54 return 0; 55 }
Problem I Reign
由题意我们可以知道我们需要求相距大于k的两个子段使其两个子段和最大。很容易想到我们可以把数组分成两部分然后枚举分割点分别求其最大子段和即可。
由于数组长度要达10E5所以我们需要预处理两个数组,pre[i]表示i之前的最大子段和,las[i]表示i之后的最大子段和。这样就解出来了。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <stack> 6 #include <queue> 7 #include <vector> 8 #include <utility> 9 #define LEN 100100 10 #define INF 0x7fffffff 11 #define ll long long 12 13 using namespace std; 14 15 int n, k; 16 ll num[LEN], pre[LEN], las[LEN]; 17 18 void init(){ 19 memset(pre, 0 ,sizeof pre); 20 memset(las, 0 ,sizeof las); 21 for(int i=1; i<=n; i++){ 22 pre[i] = pre[i-1]<0?num[i]:pre[i-1]+num[i]; 23 } 24 pre[0] = -INF; 25 for(int i=1; i<=n; i++)pre[i] = max(pre[i-1], pre[i]); 26 for(int i=n; i>=1; i--){ 27 las[i] = las[i+1]<0?num[i]:las[i+1]+num[i]; 28 } 29 las[n+1] = -INF; 30 for(int i=n; i>=1; i--)las[i] = max(las[i+1], las[i]); 31 } 32 33 int main() 34 { 35 // freopen("in.txt", "r", stdin); 36 37 int T; 38 scanf("%d", &T); 39 while(T--){ 40 scanf("%d%d", &n, &k); 41 for(int i=1; i<=n; i++){ 42 cin >> num[i]; 43 } 44 init(); 45 ll ans = -INF; 46 for(int i=1; i+k<n; i++){ 47 ans = max(ans, pre[i]+las[i+k+1]); 48 } 49 cout << ans << endl; 50 } 51 return 0; 52 }