Codeforces Round #452 (Div. 2)
D. Shovel Sale
题意:给出数 n ,你可以在 1~n 里面选取两个数,使得两数之和要尽可能以更多的 9 结尾。 问方案数。
tags:先算出结尾要多少个 9 ,然后在开头加一个数字。比如 n=50 ,最多是 99,在开头加一个数字,即 p = i 99 。
可以相加得到 p 的方案有:
1 p-1
2 p-2
3 p-3
.......
(p-1)/2 (p+1)/2
最后相加即可。
n<5 的时候,是 0 个9 。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 200005; ll n; int main() { scanf("%lld", &n); if(n<5) return 0*printf("%lld", n*(n-1)/2); int cnt=0; ll sum=1, ans=0, sum1=0; for(ll num=5; num<=n; ++cnt, num*=10, sum1+=sum*9, sum*=10) ; rep(i,0,8) { ll p = 1LL*i*sum + sum1; if(p<=n) ans += (p-1)/2; else if((p+1)/2<=n && n<p) ans += n-(p+1)/2+1; } printf("%lld ", ans); return 0; }
E. Segments Removal
题意:给出一个序列,每次从序列中删除最长最左边的连续相同子序列。问要多少次删完。
tags:链表把相同的连起来,再用堆每次选出最长最左边的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 200005; int n, a[N], cnt; bool vis[N<<2]; struct Node { int id, pre, next, fir, ai, len; bool friend operator < (Node a, Node b) { if(a.len==b.len) return a.fir > b.fir; return a.len < b.len; } } p[N<<2]; priority_queue< Node > q; int main() { scanf("%d", &n); rep(i,1,n) { scanf("%d", &a[i]); if(a[i-1]==a[i]) { ++p[cnt].len; } else { ++cnt; p[cnt] = (Node){ cnt, cnt-1, cnt+1, i, a[i], 1 }; } if(i==n) p[cnt].next=0; } rep(i,1,cnt) q.push(p[i]); int ans=0; Node u; while(!q.empty()) { u = q.top(); q.pop(); if(vis[u.id]) continue; u = p[u.id]; ++ans; vis[u.id] = true; if(u.pre==0 || u.next==0) { p[u.pre].next = u.next; p[u.next].pre = u.pre; } else { if(p[u.pre].ai==p[u.next].ai) { ++cnt; p[cnt] = (Node){ cnt, p[u.pre].pre, p[u.next].next, p[u.pre].fir, p[u.pre].ai, p[u.pre].len+p[u.next].len }; p[p[u.pre].pre].next = cnt; p[p[u.next].next].pre = cnt; vis[u.pre] = vis[u.next] = true; q.push(p[cnt]); } else { p[u.pre].next = u.next; p[u.next].pre = u.pre; } } } printf("%d ", ans); return 0; }
F. Letters Removing
题意:长度为 n 的字符串,只包含 大、小写字母和0~9数字。 有 m 个操作 l, r, c:每次删除区间 [l,r] 内的 c 字符, (给出的 l、r 是相对删除之后重新确定的位置,不是初始位置)。 求最后剩下的字符串。
tags: 好题,set 部分可以用平衡树,还不会平衡树,待补
1】每次给出的 l, r,我们把它还原回初始的位置。这个用树状数组即可,还存在的记为1,删去了的为0。
2】开62个set,在每个 set 里存对应的字符的所有位置。 每次操作在对应的set里删除在 l,r 之间的即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 200005; int n, m, bit[N]; char str[N]; set<int > Set[65]; void Add(int x, int y) { for(int i=x; i<N; i+=i&-i) bit[i] += y; } int query(int x) { int ans=0; for(int i=x; i; i-=i&-i) ans += bit[i]; return ans; } int get(char ch) { if('a'<=ch && ch<='z') return ch-'a'+1; else if('A'<=ch && ch<='Z') return ch-'A'+27; else return ch-'0'+53; } int get2(int x) { int l=1, r=n, mid, ans; while(l<=r) { mid = l+r>>1; if(query(mid)>=x) r=mid-1, ans=mid; else l=mid+1; } return ans; } int main() { scanf("%d%d", &n, &m); scanf("%s", str+1); int tmp; rep(i,1,n) { Add(i, 1); tmp = get(str[i]); Set[tmp].insert(i); } int l, r, tl, tr; char ch; set<int >::iterator it, posl, it2; rep(i,1,m) { scanf("%d%d%*c%c", &l, &r, &ch); tl = get2(l); tr = get2(r); tmp = get(ch); posl = Set[tmp].lower_bound(tl); it = posl; while(it!=Set[tmp].end() && *it<=tr) { Add((*it), -1); it2 = it; ++it; Set[tmp].erase(it2); } } rep(i,1,n) if(query(i)!=query(i-1)) putchar(str[i]); return 0; }