CF1553
CF1553
\(A\) , \(B\) 先不谈,我们先谈谈 \(C\) 的问题。
#\(C\) 状态#
C:
本题数据很小,可以考虑状压枚举,从0000000000到1111111111挨个尝试。
如何判断至少比几局呢?可以利用贪心的思想,从左到右把分加给双方,对于每一个位置,如果一方剩下全赢对方全输也无法胜利,即可停止比赛。
最后在所有状态中取最小值,即为答案。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;string s;
int main(){
cin>>t;
while(t--){
cin>>s;int ans=10;
for(int msk=0;msk<1024;msk++){
bool fl=0;
for(int i=0;i<10;i++)if((!!(msk&(1<<i)))!=(int)(s[i]-'0')&&s[i]!='?'){fl=1;break;}
if(fl)continue;
int a=0,b=0;
for(int i=0;i<10;i++){
if(i%2)a+=!!(msk&(1<<i));
else b+=!!(msk&(1<<i));
if(i==9||a+(10-i)/2<b||b+(9-i)/2<a){
if(i==2)cout<<msk<<endl;
ans=min(ans,i+1);
break;
}
}
}
cout<<ans<<endl;
}
return 0;
}
D
就类似于模拟特殊栈。
对于情况进行讨论:
- 首个字母改成退格:仅仅起到了删除某个字符的作用。
- 单独一个退格:这一个退格将原来的字符和前面一个字符通通删去,也就是连续删除了2个字符。
- 连续的 \(k\) 个退格:就是连续 \(k\) 个单独退格的效果。
从而,所有的删除操作,除去首位删除1字符外,均删除了连续2字符。
所以,\(n,m\) 奇偶性不同,必须删除首位。
用贪心,在 \(s\) 串匹配 \(t\) 串,如没匹配,说明这一位和下一位必须删除,检查是否匹配完成即可。
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
string s,t;
cin>>s;
cin>>t;
int sl=s.length(),tl=t.length();
string ss="";int j=0,k=0;
if(sl%2!=tl%2) j=1;
for(int i=j;i<sl;i++){
if(s[i]==t[k]) k++;
else i++;
if(k>=tl) break;
}
if(k<tl) puts("NO");
else puts("YES");
}
return 0;
}
E:
一句话题意:对于每个 \(k\) ,求最少多少次交换可以使一个排列变为另一个排列
做法:对于同一个数,若它在两个排列中的位置不同(记这样的数的总数为 \(s\) ),就建一条连接这两个位置的边,求得图的连通分量数 \(c\) ,答案就是 \(s−c\) 。
题中限制: \(m<\frac{n}{3}\) ,设两个排列位置一样的个数为 \(cnt_k\),
\(\sum cnt=n\) 所以满足 \(s\leq 2m\) 的 \(k\) 的数量不超过 \(3!\).
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=3e5+13;
int n,m,cnt[N],p[N],ans[N];
vector<int> g[N];
bool vis[N];
inline void add_edge(int u,int v){g[u].pb(v);}
void dfs(int u){
vis[u]=1;
for(auto v:g[u])
if(!vis[v]) dfs(v);
}
int T;
int main(){
cin>>T;
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i) cnt[i]=0;
for(int i=1;i<=n;++i){
int x;scanf("%d",&x);
p[x]=i;
cnt[(i-x+n)%n]++;//这种情况下,x这个数的位置不需要动
}
int t=0;
for(int k=0;k<n;++k){
if(cnt[k]<n-2*m) continue;//不可能成功了,直接特判掉,能往下走的k最多3个
for(int i=1;i<=n;++i) vis[i]=0,g[i].clear();
for(int i=1;i<=n;++i){
int pos=(i+k-1)%n+1;
if(pos!=p[i]) add_edge(pos,p[i]);//加边
}
int c=0;
for(int i=1;i<=n;++i){
int pos=(i+k-1)%n+1;
if(pos!=p[i]&&!vis[pos]) dfs(pos),++c;//求连通分量个数
}
if(n-cnt[k]-c<=m) ans[++t]=k;//最后判断是否可行
}
printf("%d ",t);for(int i=1;i<=t;++i) printf("%d ",ans[i]);putchar('\n');
}
// system("pause");
return 0;
}
F:
没做出来真是哈哈了
线段树+树状数组,维护 \(i*a_i\) 和 \(a_i\) 在值域维的区间和即可。
#include<bits/stdc++.h>
#define ls tree[x].lson
#define rs tree[x].rson
#define tl tree[x].l
#define tr tree[x].r
typedef long long ll;
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T& read(T& r) {
r = 0; bool w = 0; char ch = getchar();
while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
return r = w ? -r : r;
}
inline int lowbit(int x) { return x & (-x); }
const int N = 300010;
int n, a[N];
ll p[N];
struct BIT {
int m;
ll tree[N];
void init(int x) {
m = x;
for(int i = 0; i <= m; ++i) tree[i] = 0;
}
void modify(int x, ll v) { for(; x <= m; x += lowbit(x)) tree[x] += v; }
ll querysum(int x) { ll sumq = 0; for(; x; x -= lowbit(x)) sumq += tree[x]; return sumq; }
ll query(int x, int y) { return querysum(y)-querysum(x-1); }
}bit1, bit2, tr2, tr3;
struct segment_tree {
int trnt;
struct SGT {
int l, r, lson, rson;
ll sum, tag;
}tree[N << 1];
inline void pushup(int x) { tree[x].sum = tree[ls].sum + tree[rs].sum; }
inline void pushdown(int x) {
if(tree[x].tag) {
int p = tree[x].tag;
tree[ls].sum += (tree[ls].r - tree[ls].l + 1) * p;
tree[rs].sum += (tree[rs].r - tree[rs].l + 1) * p;
tree[ls].tag += p;
tree[rs].tag += p;
tree[x].tag = 0;
}
}
int build(int l, int r) {
int x = ++trnt; tree[x].sum = 0;
tl = l; tr = r;
if(l == r) return x;
ls = build(l, (l+r)>>1); rs = build(tree[ls].r+1, r);
pushup(x); return x;
}
void modify(int x, int l, int r, ll v) {
if(tl >= l && tr <= r) {
tree[x].sum += (tree[x].r - tree[x].l + 1) * v;
tree[x].tag += v;
return ;
}
int mid = (tree[x].l + tree[x].r) >> 1;
pushdown(x);
if(mid >= l) modify(ls, l, r, v);
if(mid < r) modify(rs, l, r , v);
pushup(x);
}
ll query(int x, int l, int r) {
if(tl >= l && tr <= r) return tree[x].sum;
int mid = (tree[x].l + tree[x].r) >> 1; ll sumq = 0;
pushdown(x);
if(mid >= l) sumq += query(ls, l, r);
if(mid < r) sumq += query(rs, l, r);
pushup(x);
return sumq;
}
}tr1;
int mx = 0;
signed main() {
read(n);
for(int i = 1; i <= n; ++i) read(a[i]), mx = Max(mx, a[i]);
bit1.init(mx); bit2.init(mx); tr2.init(mx); tr3.init(mx);
for(int i = 1; i <= n; ++i) {
p[i] += 1ll * a[i] * bit1.query(a[i]+1, mx);
p[i] += bit2.query(1, a[i]-1);
bit1.modify(a[i], 1);
bit2.modify(a[i], a[i]);
}
tr1.build(1, mx);
for(int i = 1; i <= n; ++i) {
p[i] += tr1.query(1, 1, a[i]);
for(int j = 1; j * a[i] <= mx; ++j) {
p[i] -= j*a[i] * tr2.query(j*a[i], Min(mx, (j+1)*a[i]-1));
p[i] += tr3.query(j*a[i], Min(mx, (j+1)*a[i]-1));
}
for(int j = 1; j * a[i] + 1 <= mx; ++j) {
tr1.modify(1, j*a[i]+1, Min(mx, (j+1)*a[i]-1), 1);
if((j+1)*a[i] <= mx)tr1.modify(1, (j+1)*a[i], (j+1)*a[i], -(Min(mx, (j+1)*a[i]-1) - (j*a[i]+1) + 1));
}
if(a[i] == 1) continue ;
tr2.modify(a[i], 1);
tr3.modify(a[i], a[i]);
}
for(int i = 1; i <= n; ++i) p[i] += p[i-1], printf("%lld ", p[i]);
// system("pause");
return 0;
}
不关注的有难了😠😠😠https://b23.tv/hoXKV9