zoukankan      html  css  js  c++  java
  • CF5

    A

    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

    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

    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

    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

    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;
    }
    
  • 相关阅读:
    P6406 [COCI2014-2015] Norma 分治+数学
    CF547D Mike and Fish 欧拉回路
    P6628 [省选联考 2020 B 卷] 丁香之路 欧拉路+最小生成树
    2020 CSP-S2 游记
    CF594D REQ 树状数组+质因数分解
    CF416E President's Path floyd
    CF1385F Removing Leaves 拓扑排序
    CF449C Jzzhu and Apples 思维题
    回溯法与八皇后问题
    codewars-7kyu:Sum of the first nth term of Series
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12232747.html
Copyright © 2011-2022 走看看