A
(map)应用
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-')f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
string s;
int sum,ret;
inline void main()
{
while(getline(cin,s))
{
if(s[0]=='+') ++sum;
else if(s[0]=='-') --sum;
else
{
int t=s.find(':');
ret+=sum*(s.size()-1-t);
}
}
cout<<ret;
}
}
signed main()
{
red::main();
return 0;
}
B
找到最长的一串,然后模拟就好了
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-')f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
string s[1010];
int maxn,opt=1,len[1010];
inline void main()
{
int i=1;
while(getline(cin,s[i]))
{
len[i]=s[i].size();
maxn=max(maxn,len[i]);
++i;
}
--i;
for(int j=1;j<=maxn+2;++j) putchar('*');
putchar('
');
for(int j=1;j<=i;++j)
{
putchar('*');
if((maxn&1)!=(len[j]&1))
{
opt=-opt;
for(int k=1;k<=(maxn-len[j]+opt)>>1;++k) putchar(' ');
cout<<s[j];
for(int k=1;k<=(maxn-len[j]-opt)>>1;++k) putchar(' ');
}
else
{
for(int k=1;k<=(maxn-len[j])>>1;++k) putchar(' ');
cout<<s[j];
for(int k=1;k<=(maxn-len[j])>>1;++k) putchar(' ');
}
puts("*");
}
for(int j=1;j<=maxn+2;++j) putchar('*');
}
}
signed main()
{
red::main();
return 0;
}
C
好题
把左括号看作(+1),右括号看作(-1),考虑一个合法子段满足的要求:子段和为(0),且不存在一个地方前缀和小于(0)
考虑维护一个(vector),里面每个前缀和出现的位置,相同前缀和之间的子段和一定为(0)
维护然后对于每个子段用个数据结构维护一下中间的前缀和最小值,如果是满足要求的子段,那么前缀和最小值应该小于与右端点
这个过程我们发现可以二分
然后(TLE)了……
然后发现其实用指针不停地往右走就行了
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-')f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e6+10;
char s[N];
int n,sum=1e6;
int ret,num=1;
int tp[N<<1];
vector<int> q[N<<1];
int ans[N<<2];
inline void update(int pos,int l,int r,int p,int k)
{
if(l==r)
{
ans[p]=k;
return;
}
if(pos<=mid) update(pos,l,mid,ls(p),k);
else update(pos,mid+1,r,rs(p),k);
ans[p]=min(ans[ls(p)],ans[rs(p)]);
}
inline int query(int tl,int tr,int l,int r,int p)
{
if(tl<=l&&r<=tr) return ans[p];
int ret=1e9+7;
if(tl<=mid) ret=min(ret,query(tl,tr,l,mid,ls(p)));
if(tr>mid) ret=min(ret,query(tl,tr,mid+1,r,rs(p)));
return ret;
}
inline void main()
{
scanf("%s",s+2);
n=strlen(s+2)+1;
q[sum].push_back(1);
update(1,1,n,1,sum);
for(int i=2;i<=n;++i)
{
if(s[i]=='(') ++sum;
else --sum;
update(i,1,n,1,sum);
q[sum].push_back(i);
while(query(q[sum][tp[sum]],i,1,n,1)<sum) ++tp[sum];
int now=q[sum][tp[sum]];
if(i-now==ret) ++num;
if(i-now>ret) ret=i-now,num=1;
}
if(!ret) num=1;
printf("%d %d
",ret,num);
}
}
signed main()
{
red::main();
return 0;
}
D
纯高中物理题……也就是俗说的假伯题
懒得自己推了直接颓了题解
题解的(code)好精简啊
设(f(v_0,v,a,l))表示初速度为(v0),速度不能超过(v),加速度为(a),走过(l)花费的时间
分类讨论:
(v^2-v_0^2=2ax -> x=frac{v^2-v_0^2}{2a})
一直加速((l<=x)):(l=-frac{1}{2}at^2+v_0t -> t=frac{-v_0+sqrt{v_0^2+2al}}{a})
先加速再匀速一段((l>x)):(t=frac{v-v_0}{a}+frac{l-x}{v})
如果我们速度达到(w)的位置在(d)之后,或者(w>=v),那么答案就是(f(0,v,a,l))
否则仍然要分类讨论:
先单独考虑(d)到(l),这段时间为(f(w,v,a,l-d))
在(d)之前:
假设我们没有(v)的限制,加速时间为(t),那么这个过程应该是大力先飙车再大力刹车
也就是(t=t加速+t减速)
(t=t加速+t减速到0-t加速到w)
列方程:(2a^2t^2-w^2=2ad -> t=sqrt{frac{2ad+w^2}{2a^2}})
然后我们看这个加速时间能达到的最大速度有没有达到(v)
先加速再减速((at<=v)):花费时间为(t^2-frac{w}{a})
先加速然后匀速再减速:花费时间为(frac{v}{a}+frac{v-w}{a}+frac{d-加速路程-减速路程}{v})
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-')f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
double a,v;
double l,d,w,ans,t1,t2;
inline double F(double x)
{
return x*x;
}
inline double f(double v0,double v,double a,double l)
{
double s=(v+v0)*(v-v0)/2/a;
if(s>=l) return (-v0+sqrt(F(v0)+2*a*l))/a;
else return (v-v0)/a+(l-s)/v;
}
inline void main()
{
scanf("%lf%lf%lf%lf%lf",&a,&v,&l,&d,&w);
double stp=F(w)/2/a;
if(w>=v||stp>=d) ans=f(0,v,a,l);
else
{
t2=f(w,v,a,l-d);
double tjs=sqrt((2*a*d+F(w))/2/a/a);
if(tjs*a<=v) t1=2*tjs-w/a;
else
{
double sf=F(v)/2/a;
double sl=(v+w)*(v-w)/2/a;
t1=v/a+(v-w)/a+(d-sf-sl)/v;
}
ans=t1+t2;
}
printf("%.12f
",ans);
}
}
signed main()
{
red::main();
return 0;
}
E
一个环,环上一堆山,每个山一个高度,两个山头能互相看见当当且仅当中间没有更高的山
先考虑把最大的挪到(n)的位置,然后在(0)也补上一个
然后记录(l[i],r[i])表示左右第一个大于自己的位置,和(c[i])表示([i,r[i]))中和自己相等的数量
那么每个数字的贡献是(l[i],r[i])两个和(c[i])的数量
注意 (l[i]==0)且(r[i]==n)时是同一种情况,要减一
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-')f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e6+10;
int n,ret,pos;
int h[N],a[N],l[N],r[N],c[N];
inline void main()
{
n=read();
for(int i=0;i<n;++i)
{
h[i]=read();
if(h[i]>h[pos]) pos=i;
}
for(int i=0;i<=n;++i)
{
a[i]=h[(i+pos)%n];
}
for(int i=1;i<=n;++i)
{
l[i]=i-1;
while(l[i]&&a[i]>=a[l[i]]) l[i]=l[l[i]];
}
for(int i=n-1;~i;--i)
{
r[i]=i+1;
while(r[i]&&a[i]>a[r[i]]) r[i]=r[r[i]];
if(r[i]<n&&a[i]==a[r[i]]) c[i]=c[r[i]]+1,r[i]=r[r[i]];
}
for(int i=0;i<n;++i)
{
ret+=c[i];
if(a[i]<a[0])
{
ret+=2;
if(!l[i]&&r[i]==n) --ret;
}
}
printf("%lld
",ret);
}
}
signed main()
{
red::main();
return 0;
}