标签:逆序 clu 树状 getchar mod ... nbsp cin strlen
假的div2 C题没事写什么公式被卡精度了,掉分了gg
---------------------------------------------------
A....几个每个字符串预先给好一个代表的值,给n个字符串,求和。
题解:手速题。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #define ll long long #define INF 2000000000 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } map<string,int> mp; int n; ll ans=0; string st; int main() { n=read();mp["Tetrahedron"]=4; mp["Cube"]=6; mp["Octahedron"]=8; mp["Dodecahedron"]=12; mp["Icosahedron"]=20; for(int i=1;i<=n;i++) cin>>st,ans+=mp[st]; cout<<ans; return 0; }
B.有两种课,每种课都有很多节,每节课有一段时间l..r,你要从两种课中都选一节,使得中间的休息时间最长。
题解:两边都分别记一下最小值,最大值。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #define ll long long #define INF 2000000000 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } int mx1,mx2,mn1=INF,mn2=INF; int n,m,ans=0; int main() { n=read(); for(int i=1;i<=n;i++) { int l=read();int r=read(); mx1=max(mx1,l);mn1=min(mn1,r); } m=read(); for(int i=1;i<=m;i++) { int l=read();int r=read(); mx2=max(mx2,l);mn2=min(mn2,r); } ans=max(ans,max(mx1-mn2,mx2-mn1)); cout<<ans; return 0; }
C.有一个大小为n的粮仓,一开始是满的,每天都会运来m的粮食,但是不能超过大小上限,然后运来后会有不速之客来吃,第i天吃掉i的粮食,求第几天粮食被吃完了。
n,m<=10^18
正确解法:二分答案,等差数列求和
我的错误解法:解一元二次方程,结果用了double被卡精度,FST了,改成long double 就过了.... 心累。
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #include<cmath> #define ll unsigned long long #define double long double #define INF 2000000000 #define eps 1e-8 using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } ll n,m,size; int main() { n=read();m=read(); if(n<=m)cout<<n; else { double mm=sqrt((double)n*2.0-(double)m*2.00+0.25)-0.5; m+=(ll)ceil(mm); cout<<m; } return 0; }
D.给定一个长度为n的括号序列,求特殊的括号子序列的数量。特殊的是指,前一半是(,后一半是) n<=200000
左边有n个左括号,右边有m个右括号,我们为了去重要求一定选最右的哪个左括号,这是侯答案数量是∑C(n,k-1)*C(m,k) k=1..min(n,m)
然后我们会发现这个式子就等于C(n+m-1,m-1),所以预处理好阶乘和逆元,就可以算啦。
复杂度O(n)
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<map> #include<cmath> #define ll long long #define INF 2000000000 #define mod 1000000007 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } int n; char s[200005]; ll p[200005],l[200005]; int num1=0,num2=0; ll ans=0; ll work(int n,int c) { return p[n]*l[c]%mod*l[n-c]%mod; } int main() { scanf("%s",s+1);n=strlen(s+1); p[0]=l[0]=l[1]=1; for(int i=1;i<=200000;i++)p[i]=p[i-1]*i%mod; for(int i=2;i<=200000;i++)l[i]=(mod-mod/i)*l[mod%i]%mod; for(int i=2;i<=200000;i++)l[i]=l[i]*l[i-1]%mod; for(int i=1;i<=n;i++)num2+=(s[i]==‘)‘); for(int i=1;i<=n;i++) { if(s[i]==‘)‘)num2--; else {num1++;ans=(ans+work(num1+num2-1,num2-1))%mod;} } cout<<ans; return 0; }
E.给定一个1-n的全排列,一开始是1到n摆放。q个操作,每次交换一对数,然后要求交换后的逆序对数量。n<=200000,q<=50000
1.分块+树状数组。复杂度应该是n^1.5*logn
2.树状数组套平衡树.....(ditoly真的强,几下就切完了)复杂度nlog^2n
代码之后补。
标签:逆序 clu 树状 getchar mod ... nbsp cin strlen
原文地址:http://www.cnblogs.com/FallDream/p/codeforces785.html