标签:char efi str math signed 结构 cin max 指针
\(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;
}
找到最长的一串,然后模拟就好了
#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('\n');
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;
}
好题
把左括号看作\(+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\n",ret,num);
}
}
signed main()
{
red::main();
return 0;
}
纯高中物理题……也就是俗说的假伯题
懒得自己推了直接颓了题解
题解的\(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\n",ans);
}
}
signed main()
{
red::main();
return 0;
}
一个环,环上一堆山,每个山一个高度,两个山头能互相看见当当且仅当中间没有更高的山
先考虑把最大的挪到\(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\n",ret);
}
}
signed main()
{
red::main();
return 0;
}
标签:char efi str math signed 结构 cin max 指针
原文地址:https://www.cnblogs.com/knife-rose/p/12232747.html