下午打了场gym,撸文化课笔记心累就随便写一写吧。
本人能力有限,只放我做了的几道。
http://codeforces.com/gym/100812
B set of tasks
题意杀,一开始以为是要求什么距离和最小这种很傻的东西怒WA一发然后又被阳神训斥了
阳神说题意是有5000个长度5000的01串,要你找出现次数最多的一个输出,要求这个01串里1不能超过15个或小于8个并没有什么卵用直接HASH或者map乱搞应该就能过,其实bitset排序硬上O(5000/32*5000*log(5000))应该也不怂但是撸完G题还有15分钟就没写
D dream of sum
一个序列要你求最短和为0的子序列。Map或者hash链乱搞,懒得写这两个就排序了沙雕题WA3发
#include<cstdio>
#include<algorithm>
using namespace std;
long long sum;
struct ele{
long long s;
int k;
}e[200005];
int n,x,cnt,ans1,ans2;
inline bool cmp(ele k1,ele k2){
if(k1.s!=k2.s)return k1.s<k2.s;
else return k1.k<k2.k;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
sum+=x;
e[i].k=i;
e[i].s=sum;
}
sort(e,e+1+n,cmp);
ans2=n+2;
for(int i=1;i<=n;i++)if(e[i].s==e[i-1].s){
if(e[i].k-e[i-1].k<ans2){
ans1=e[i-1].k+1;
ans2=e[i].k-e[i-1].k;
}
}
if(ans2==n+2)printf("-1");
else printf("%d %d\n",ans1,ans2);
}
E world of knights
一开始把题名看成了world of knives觉得好中二
有若干张牌,有两个属性ai,bi,初始你有一张属性为0,1的牌,然后你可以用手里的一张牌i来获得另外一张牌j,满足bi>=aj,求获得第n张牌的最小操作数(即你最少要拿几张牌来获得第n张牌)并输出方案。
一开始以为是什么单点修改然后线段树求最小值这种东西。线段树已经打好了一看,这TM不是个SB单调栈吗(╯‵□′)╯︵┻━┻。然后怒打单调栈沙雕题又怒WA一发
#include<cstdio>
#include<algorithm>
#define inf 2000000000
#define lson index<<1
#define rson index<<1
using namespace std;
int n,stack[100005],pre[100005],top,cnt;
struct ele{
int a,b,pre,k;
}e[100005],E[100005];
bool cmp(ele k1,ele k2){
if(k1.a!=k2.a)return k1.a<k2.a;
else return k1.b>k2.b;
}
void print(int k,int s){
if(k){
print(e[k].pre,s+1);
printf("%d ",e[k].k);
}else printf("%d\n",s);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&E[i].a,&E[i].b),E[i].k=i;
if(n==1){
if(E[1].a==0)printf("1\n1");
else printf("No such luck");
return 0;
}
sort(E+1,E+n,cmp);
cnt=1;e[1]=E[1];
for(int i=2;i<n;i++)if((E[i].a>e[cnt].a)&&(E[i].b>e[cnt].b)){
cnt++;
e[cnt]=E[i];
}
e[0].a=0;e[0].b=1;top=1;stack[1]=0;
for(int i=1;i<=cnt;i++){
if(e[i].a>e[i].b)continue;
int l=0,r=top+1;
while(r-l>1){
int mid=(l+r)>>1;
if(e[stack[mid]].b>=e[i].a)r=mid;
else l=mid;
}
if(r==top+1)continue;
e[i].pre=stack[r];
top++;
stack[top]=i;
}
int l=0,r=top+1;
while(r-l>1){
int mid=(l+r)>>1;
if(e[stack[mid]].b>=E[n].a)r=mid;
else l=mid;
}
if(r==top+1){
printf("No such luck");
return 0;
}else{
print(stack[r],1);
printf("%d",n);
}
}
F Graveyard of Bandits
题意给你一个n*m的*.矩阵,你可以在所有.的地方建墓碑,问你建1*1,1*2,1*3...1*max(n,m)的矩阵的方案数。
第一眼看n,m<=105吓了一跳,发现后面还有一个n*m<=106
统计出来图中所有1*1,1*2,1*3,...,1*max(n,m)的独立矩阵数(这些矩阵不能再合并成1*k),显然在一个1*i的矩阵里选一个1*j的矩阵方案是i-j+1种,前缀和乱搞搞就行,然后这样做一遍就能得到所有横着建的方案数。
然后1*1,2*1,3*1,...,max(n,m)*1竖着再搞一遍就好了,注意1*1会算两次特判掉。
#include<cstdio>
using namespace std;
int n,m;
char c[1000005];
int ans[100005];
long long A[100005];
inline int max(int x,int y){return x>y?x:y;}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)scanf("%s",c+i*m);
for(int i=0;i<n;i++){
int s=0;
for(int j=0;j<m;j++)if(c[i*m+j]=='.')s++;
else{
if(s)ans[s]++;
s=0;
}
if(s)ans[s]++;
}
for(int j=0;j<m;j++){
int s=0;
for(int i=0;i<n;i++)if(c[i*m+j]=='.')s++;
else{
if(s)ans[s]++;
s=0;
}
if(s)ans[s]++;
}
long long Ans=0,sum=0;
for(int i=max(n,m);i;i--){
sum+=ans[i];
Ans+=sum;
if(i>1)A[i]=Ans;
else A[i]=Ans/2;
}
for(int i=1;i<=max(n,m);i++)printf("%I64d ",A[i]);
}
G short path
吃完饭做的,所以没有时间打B了。
题意:给你一个20W点10W边的图,其中某些点有标记,求有标记的点之中的两点最短距离。
看边比较小感觉标算应该很巧妙,不是很会来,直接上k次SPFA,k次v全部初始化显然T,所以打了时间戳。
跑80点啥事没有很开心,然后TLE101CF卡SPFA丧心病狂
然后上读入优化还是TLE101,然后
if(clock()>=1800){
if(ans==1LL*n*1000000000)printf("No luck at all");
else printf("%I64d\n%d %d",ans,x,y);
return 0;
}
A掉了
#include<cstdio>
#include<ctime>
using namespace std;
int f[200005],head[200005],dl[200005],B[200005];
long long v[200005];
int n,m,x,y,l,r,times,cnt;
bool b[200005];
long long ans;
struct edge{
int next,to,l;
}e[200005];
inline long long min(long long x,long long y){return x<y?x:y;}
void add(int x,int y,int l){
cnt++;
e[cnt].next=head[x];
e[cnt].to=y;
e[cnt].l=l;
head[x]=cnt;
}
inline int read(){
int ret=0;
char c=getchar();
while((c>'9')||(c<'0'))c=getchar();
while((c>='0')&&(c<='9'))ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
return ret;
}
void spfa(int root){
times++;B[root]=times;
v[root]=0;
l=r=1;dl[1]=root;b[root]=true;
while(true){
if((f[dl[l]])&&(dl[l]!=root)&&(ans>v[dl[l]])){
ans=v[dl[l]];
x=root;
y=dl[l];
}
for(int i=head[dl[l]];i;i=e[i].next)if(((B[e[i].to]<times)||(v[e[i].to]>v[dl[l]]+e[i].l))&&(v[dl[l]]+e[i].l<ans)){
B[e[i].to]=times;
v[e[i].to]=v[dl[l]]+e[i].l;
if(!b[e[i].to]){
r++;
if(r>n)r=1;
dl[r]=e[i].to;
b[e[i].to]=true;
}
}
b[dl[l]]=false;
if(r==l)break;
l++;
if(l>n)l=1;
}
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++)f[i]=read();
while(m--){
x=read();y=read();l=read();
add(x,y,l);
add(y,x,l);
}
ans=1LL*n*1000000000;
for(int i=1;i<=n;i++)if(f[i]){
spfa(i);
if(clock()>=1800){
if(ans==1LL*n*1000000000)printf("No luck at all");
else printf("%I64d\n%d %d",ans,x,y);
return 0;
}
}
if(ans==1LL*n*1000000000)printf("No luck at all");
else printf("%I64d\n%d %d",ans,x,y);
}
后来去看不知道是凌神还是YB的代码,这个东西好像只要BFS就行_(:зゝ∠)_果然还是我太沙雕的缘故
I Dragon Delivers
题意:给你若干个订单,每个订单可以有两种办法交付,第一种直接交付,代价为d,第二种和他之前第一个直接交付的订单合并,代价为(ti-tj)*c,求最小交付所有订单的方法。
dp方程很好写,dp[i]=min(dp[j]+(sum[i]-sum[j]-t[j+1]*(i-j))*c+d)感觉好像可以斜率优化。
一看数据范围,n=1k,呵呵。稍微处理一下就能去掉前缀和。
#include<cstdio>
#include<algorithm>
using namespace std;
int n,d,c;
int x[1005];
long long dp[1005];
int main(){
scanf("%d%d%d",&n,&d,&c);
dp[0]=0;
for(int i=1;i<=n;i++)scanf("%d",&x[i]);
for(int i=1;i<=n;i++){
dp[i]=dp[i-1]+d;
long long s=0;
for(int j=i-1;j>=1;j--){
s+=x[i]-x[j];
dp[i]=min(dp[i],s*c+dp[j-1]+d);
}
}
printf("%I64d\n",dp[n]);
}
J Feeling of Comradeship
初三大爷做的,我不知道。有需要的去问初三大爷一号
L Knights without Fear and Reproach
题意:有两个人一起打你,第一个人每a秒打你一下,第二个人每b秒打你一下,你假如有两秒之内被打两次就GG,问你什么时候会GG。
一眼感觉好厉害,第二眼沙雕题,只有两种可能exgcd或者lcm,别和我说你不会。
注意特判a,b里有1的情况,我没特判怒WA一发_(:зゝ∠)_
#include<cstdio>
#include<algorithm>
using namespace std;
int a,b,gcd,x,y,A,B;
long long ans;
inline int exgcd(int x, int y, int&a, int&b) {
if(y==0){
a=1,b=0;
return x;
}
int g=exgcd(y,x%y,a,b);
int t=a;
a=b;
b=t-x/y*b;
return g;
}
int main(){
scanf("%d%d",&x,&y);
if((x==1)&&(y==1)){
printf("1");
return 0;
}
if((x==1)||(y==1)){
printf("2");
return 0;
}
int gcd=exgcd(x,y,a,b);
ans=1LL*x*y/gcd;
if(gcd>1){
printf("%I64d",ans);
return 0;
}
if(a>0)ans=min(ans,1LL*a*x);
else ans=min(ans,1LL*b*y);
printf("%I64d\n",ans);
}
1、文化课积重难返心累啊
2、哲教阳神YB一群人看我和初三大爷在打gym就来殴打小盆友简直丧心病狂
2016年2月01日 22:02
你就不能好好叫我名字吗orz叫简拼也比这玩意好啊魂淡!(掀