题解:USACO23OPEN-Silver
题解:USACO23OPEN-Silver
T1 Milk Sum
给定一个长度为 \(N\) 的序列 \(a_1,a_2,...,a_n\),现在给出 \(Q\) 次操作每次将 \(a_x\) 修改为 \(y\) , 每次修改后,求将序列重排后的 \(T\) 的最大值,定义 \(T=\sum_{i=1}^{n}i \times a_i)\)
每次修改数组后会将序列还原成原样(修改不继承)
有一个显然的结论:对于\(\forall 0<a<b, 0<c<d\) ,满足\(a*c+b*d>a*d+b*c\)
所以将序列从小到大排序得到的 \(T\) 一定更大
所以预先把排好的原序列存下来,对于每次修改只需要二分出修改后应放的位置,然后(1)减掉原来数的贡献,(2)加上现在数的贡献,(3)所有位置后挪1或前挪1的贡献变化
注意二分后查询时的细节(加1减1)。
#include<bits/stdc++.h>
#define F(i,l,r) for(int i=l;i<=r;++i)
#define G(i,r,l) for(int i=r;i>=l;--i)
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
char buf[100],*p1=buf,*p2=buf;
inline int gc(){ return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++; }
inline int rd(){
int x=0; char ch=gc(); bool f=1;
while(!isdigit(ch)) f^=(ch=='-'),ch=gc();
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=gc();
return f?x:-x;
}
const int N=2e5+5;
ll sum[N],tot=0,a[N],b[N],n,q,x,y;
int main(){
// freopen("a.in","r",stdin);freopen("a.out","w",stdout);
n=rd(); F(i,1,n) a[i]=rd(),b[i]=a[i]; sort(b+1,b+n+1);
F(i,1,n) tot+=b[i]*i,sum[i]=sum[i-1]+b[i];
q=rd(); while(q--){
x=rd(),y=rd();
int u=upper_bound(b+1,b+n+1,y)-b,v=lower_bound(b+1,b+n+1,a[x])-b;
if(v>=u) printf("%lld\n",tot-v*a[x]+u*y+sum[v-1]-sum[u-1]);
else printf("%lld\n",tot-v*a[x]+(u-1)*y+sum[v]-sum[u-1]);
}
return 0;
}
T2 Field Day
(又是逆向思维题...)
给出 \(N\) 个长度为 \(C\) 的 \(GH\) 串,将 \(G\) 看作 \(0\) ,将 \(H\) 看作 \(1\) , 则每个串可看做01串,对于每个 \(i\) ,求 \(max_{j=1}^{n} popcount(a_i \oplus a_j)\)
\(2 \leq N \leq 10^5,1 \leq C \leq 18\)
暴力是 \(O(N^2)\) 的,发现本题的特点如下:
(1) \(C\) 很小,算一下本质不同的 \(01\) 串只有 \(2^{18}\) 个,大概是25万多一点。
※(2)最大值不是很好求,考虑倒过来想,转化成求最小值。
(3)与串 \(a_i\) 差异度为 \(k\) 的一个串 \(t\) 可以看做是 将 \(a_i\) 的其中 \(k\) 个数一步一步取反后得到的。
一个数可以由多个给出的串通过这样的取反变化得到,但我们只关心至少要改变几个数位才能得到 \(t\)(求最小值嘛),所以如果我们能找到一种操作顺序,使第一次得到 \(t\) 花的就是最少步数的话,那\(0-2^c-1\) 下的每个数都只需要访问一遍就可以了!
什么样的操作顺序使我们需要的呢?灵光一现,考虑广搜,先搜出每个串改1个数位能得到的结果,再考虑改2个数,再改3个,4个....一直到 \(c\) 个,每次都把上一层更新出的数存下来用于下一层更新,访问过的数不再重复访问,时间复杂度 \(O(2^C)\)。
广搜写法:
#include<cstdio>
#include<queue>
using namespace std;
#define ri register int
#define F(i,l,r) for(ri i=l;i<=r;++i)
const int N=1e5+5;
queue<int> q;
int c,n,a[N],f[(1<<18)+100];
char s[22];
bool vis[(1<<18)+100];
int main(){
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d",&c,&n);
F(i,1,n){
scanf("%s",s+1);
int sum=0;
F(j,1,c) sum=(sum<<1)+(s[j]=='G');
a[i]=sum; q.push(sum); vis[sum]=1;
}
while(q.size()){
int x=q.front();q.pop();
F(i,1,c){
int y=x^(1<<(i-1));
if(vis[y] || f[y]) continue;
f[y]=f[x]+1;
vis[y]=1; q.push(y);
}
}
F(i,1,n) printf("%d\n",c-f[(1<<c)-1-a[i]]);
return 0;
}
用循环模拟广搜:
#include<cstdio>
using namespace std;
#define ri register int
#define F(i,l,r) for(ri i=l;i<=r;++i)
#define min(x,y) x<y?x:y
const int N=1e5+5;
int sum,c,n,a[N],f[(1<<18)+100];
char s[22];
int main(){
freopen("b.in","r",stdin); freopen("b.out","w",stdout);
scanf("%d%d",&c,&n);
F(i,0,(1<<c)-1) f[i]=99999999;
F(i,1,n){
scanf("%s",s+1);
sum=0;
F(j,1,c) sum=(sum<<1)+(s[j]=='G');
f[sum]=0;
a[i]=sum;
}
F(i,1,c) F(j,0,(1<<c)-1) f[j^(1<<i-1)]=min(f[j^(1<<i-1)],f[j]+1);
F(i,1,n) printf("%d\n",c-f[(1<<c)-1-a[i]]);
return 0;
}
结合两种方法而观之,发现循环其实是dp,广搜其实是记搜...
好好好万物皆可dp是吧
T3 Pareidolia
给定一个仅包含小写字母的字符串 \(s\) , 长度不超过 \(3 \times 10^5\)。
定义函数 \(B(s)\) 表示把 \(s\) 中的若干个字母删去后,形成尽量多个bessie
相连的形式(bessiebessiebessie...
),返回bessie
的最大数量。
如 \(B(\text{"bqessiyexbesszieb"})=2\)。
求 \(s\) 的所有子串的 \(B\) 函数之和。
两个误区:
(1)一个字符最多只能存在于一个bessie中而非多个。还担心会不会一匹配多,把问题想复杂了
(2)审题不清:没发现任意字母都可以删去,还以为是KMP,写到最后再读题发现问题之后哭死,只剩不到1h,直接失去继续写下去的动力了。。。(想好再下笔!!!)
对我来说,光是如何简明地书写判断是否找到了一个新的bessie都有难度。。。
由于模式串是固定的而且只有六位,直接对于 b,e,s,i
这几种字符记录我所在的bessie串的开头b所在的位置即可。开头记录下来,串的位置当然也就确定啦!而且后面统计答案还要用到
考虑新发现一个bessie串对答案的贡献。记 \(f_i\) 为以i结尾的所有子串的B函数之和,\(pos\) 为新发现的bessie串的开头位置。则有
\]
emm...可以感性理解为:继承没发现这个串之前的答案 + 起点为1-pos,终点固定成i的所有串都会多看到当前这个新串。
最终答案 \(sum=\sum_{i=1}^{n} f_i\)
注意有些字符的更新是有顺序的,不要写挂了。
#include<cstdio>
const int N=3e5+5;
char s[N];
int p[10];
long long f[N],sum=0;
int main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%s",s+1);
for(int i=1;s[i];++i){
// F(i,1,6) printf("%d ",p[i]); puts("");
if(s[i]=='b') p[1]=i;
else if(s[i]=='e') p[2]=p[1],p[6]=p[5];
else if(s[i]=='s') p[4]=p[3],p[3]=p[2];//不能写反,否则一个's'会同时更新p[4],p[3]
else if(s[i]=='i') p[5]=p[4];
if(p[6]) f[i]=f[p[6]-1]+p[6];
//f[i]:以i结尾的所有子串的B函数之和
//p[6]:以i结尾的能含有当前这个新增bessie的子串的数量
//p[6]位置以前的所有串还能多包含一个bessie(即当前新增的这个),所以要+f[p[6]-1]
sum+=f[i];
} printf("%lld",sum);
return 0;
}
存疑:为什么下面这种写法是错的???
#include<bits/stdc++.h>
using namespace std;
char c[300005];
unsigned long long p[10];
int main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%s",c+1);
unsigned long long lenc=strlen(c+1);
unsigned long long ans=0;
unsigned long long sum=0;
for(unsigned long long i=1;i<=lenc;i++){
if(c[i]=='b') p[1]=i;
if(c[i]=='e'){
p[2]=p[1];
if(p[5]!=p[6]) sum+=p[5];
p[6]=p[5];
}
if(c[i]=='s') p[4]=p[3],p[3]=p[2];
if(c[i]=='i') p[5]=p[4];
ans+=sum;
}
printf("%llu",ans);
return 0;
}
模拟赛总结:
1.感觉T1写了近两个小时有点慢了,如果把找 \(a_x\) 原位置直接也写成lower_bound可能会节省很多时间(毕竟每写一个二分查总是要调很久...)
2.T2部分分拿的还是很稳的,但对于C较小这个性质的运用还是差了些:只想到了用bitset优化异或过程。还有,积累逆向思维的经验:原问题不好想,那就承认它不好想,就大胆考虑倒过来想
(由于正着做不好想,所以我们考虑倒过来想)
3.T3首先审题不清(想好再下笔),第二想复杂了,被吓到了(还是要多手玩几个样例去自己体会题目的要求,不要偷懒 ~ ~ ~)
写在最后:距离NOIP2023仅剩16天,耳边又想起了中考前我的语文老师告诉我的那句话,
“行百里者半九十。”
希望不留遗憾~加油NOIP2023!
题解:USACO23OPEN-Silver的更多相关文章
- 洛谷 P1821 [USACO07FEB]银牛派对Silver Cow Party 题解
P1821 [USACO07FEB]银牛派对Silver Cow Party 题目描述 One cow from each of N farms (1 ≤ N ≤ 1000) conveniently ...
- usaco silver刷水~其实是回顾一下,补题解
[BZOJ1606][Usaco2008 Dec]Hay For Sale 裸01背包 ;i<=n;i++) for(int j=m;j>=a[i];j--) f[j]=max(f[j], ...
- POJ 3268 Silver Cow Party(最短路&Dijkstra)题解
题意:有n个地点,有m条路,问从所有点走到指定点x再走回去的最短路中的最长路径 思路:用Floyd超时的,这里用的Dijkstra. Dijkstra感觉和Prim和Kruskal的思路很像啊.我们把 ...
- 【luogu P1821 [USACO07FEB]银牛派对Silver Cow Party】 题解
题目链接:https://www.luogu.org/problemnew/show/P1821 反向多存一个图,暴力跑两遍 #include <cstdio> #include < ...
- USACO 2013 Nov Silver Pogo-Cow
最近因为闲的蛋疼(停课了),所以开始做一些 USACO 的银组题.被完虐啊 TAT 貌似 Pogo-Cow 这题是 2013 Nov Silver 唯一一道可说的题目? Pogo-Cow Descri ...
- POJ 3268 Silver Cow Party (最短路dijkstra)
Silver Cow Party 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/D Description One cow fr ...
- poj 3268 Silver Cow Party(最短路)
Silver Cow Party Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17017 Accepted: 7767 ...
- 1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区(题解第二弹)
1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: ...
- 1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区(题解第一弹)
1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: ...
- POJ 3268 Silver Cow Party 最短路径+矩阵转换
Silver Cow Party Time Limit : 4000/2000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) T ...
随机推荐
- 并查集基础 &打击罪犯
并查集基础 真的很基础 题目描述:Description 某个地区有n(n<=1000)个犯罪团伙,当地警方按照他们的危险程度由高到低给他们编号为1-n,他们有些团伙之间有直接联系,但是任意两个 ...
- 免费word简历 简历制作平台
分享一个简历制作平台. 免费的word模版 链接地址 https://www.xyjianli.com/ https://www.xyjianli.com/list https://www.xyjia ...
- spring同时集成mybatis和ibatis
最近来了一个新项目,说是新的项目,但是需要用到以前旧的模块代码,旧的模块使用架构为ssi 而新项目使用spring mvc +mybatis,考虑到工作量的问题,所以决定使用spring mvc +m ...
- Argo CD初体验
什么是 Argo CD? Argo CD 是一个声明式的 GitOps 持续交付工具,用于 Kubernetes 集群.它通过持续监控 Git 仓库中的 Kubernetes 资源配置文件,将这些配置 ...
- 小tips:HTML5的ruby标签实现给汉字加拼音、details标签实现折叠面板、原生进度条progress和度量meter
ruby标签实现给汉字加拼音 ruby 元素由一个或多个字符(需要一个解释/发音)和一个提供该信息的 rt 元素组成,还包括可选的 rp 元素,定义当浏览器不支持 "ruby" 元 ...
- BOM – Navigator SendBeacon
介绍 游览器专门做给 tracking 用的接口. 从前我们想 tracking 用户点击 anchor 是比较麻烦的. 因为 click 事件触发后, 想发 ajxax 去做 tracking re ...
- Identity – Authorize Custom Authorization Policy Providers
前言 上一篇讲完了基本使用 Policy-Based. 这一篇另外说一说怎么动态调用它. 参考: Custom Authorization Policy Providers using IAuthor ...
- CSP提高组模拟1
我的微軟輸入法莫名其妙變成繁體了,你們有什麽頭緒嗎 狀態 題目 20 Time Exceeded A 最短路 25 Time Exceeded B 方格取数 0 Time Exceeded C 数组 ...
- C++的并发编程历史
多线程环境 并非所有的语言都提供了多线程的环境.即便是C++语言,直到C++11标准之前,也是没有多线程支持的. 在这种情况下,Linux/Unix平台下的开发者通常会使用POSIX Threads, ...
- CPU缓存伪共享
CPU缓存什么东西?当然这个问题很多人有可能觉得比较傻,CPU缓存什么,肯定是缓存数据(代码)啊,要不然还能缓存啥,这个确实没问题,但是CPU到底缓存什么样的数据呢?因为对CPU来说,无论是指令,还是 ...