感觉自己的弱点在代码实现上面,就是知道怎么写但写要很久而且易错难调,解决措施:
1.敲键盘之前要画好流程图,想好一共需要几个函数,函数的功能以及要怎么实现,需要用到哪些库函数哪些数据结构等等,思路要清晰,思路清不清晰看程序就知道。
2.如果是改程序,就先理清楚标程是怎么实现的,基本上按照标程写,把握标程好的代码特色。
3.如果是调试,就在每一步理清楚程序的数学本质,如果还调不好就:
1)对比标程,有利于对程序的理解(改考试时)
2)用易错数据,有利于培养考试能力(平时刷题时);
注意效率,不要一直交一直错。
来正事:
T1:
题意:给定x,y轴正半轴上的n个点,一一相连使不相交,然后针对每个提问(共m个)回答与多少条线段相交。
分析:
一眼二分题。
即对x,y轴上的点排序,对每个询问,二分在x,y轴上的点的相对位置,判断是否相交。
二分很容易错,要么就老老实实地进行检验,要么就用好的模板(我选择两个一起)(下面附模板)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define clr(x) memset(x,0,sizeof(x))
using namespace std;
const int maxn=1e5+5;
int n,q;
long long x[maxn],y[maxn],cur1,cur2;
int read()
{
char tmp[11];int ret=0;clr(tmp);
scanf("%s",tmp);int len=strlen(tmp);
for(int i=0;i<len;i++)ret=ret*10+tmp[i]-'0';
return ret;
}
void init()
{
n=read();
for(int i=1;i<=n;i++)x[i]=(long long)read();
for(int i=1;i<=n;i++)y[i]=(long long)read();
q=read();sort(x+1,x+n+1);sort(y+1,y+n+1);
}
void work()
{
int lef=0,rig=n,mid;
while(lef<=rig){
mid=(lef+rig)/2;
long long res1=cur2*x[mid]+cur1*y[mid];
long long res2=x[mid]*y[mid];
if(res1>res2)lef=mid+1;
else if(res1<res2)rig=mid-1;
else break;
}
mid=(rig+lef)/2;
long long res1=cur2*x[mid]+cur1*y[mid];
long long res2=x[mid]*y[mid];
if(res1<res2)mid--;
res1=cur2*x[mid+1]+cur1*y[mid+1];
res2=x[mid+1]*y[mid+1];
if(res1>res2)mid++;
printf("%d\n",mid);
}
int main()
{
freopen("geometry.in","r",stdin);
freopen("geometry.out","w",stdout);
init();
for(int i=1;i<=q;i++){
cur1=(long long)read();
cur2=(long long)read();
work();
}
return 0;
}
某大神的模板,基本上不用判断,不过考试的时候还是分析一下会不会有特殊情况吧。
int l=1 , r=n+1;
while(l<r) // the minimum line above P(x0,y0)
{
int m = (l+r)>>1;
if(check(m)) r = m;//在下面;
else l = m + 1;
}
return l-1;
(为什么不特判:每次都是l在加一,则最后出问题的要么是r=l+1时m=l不满足,则l-1可以
要么是l=m+1=r时m满足r不满足,则l-1也可以
综上,该返回值总是没问题。)
T2:
题意:在一棵树上某个点可以付出一些代价获取向上走若干步的能力,且在走的过程中可以放弃已获得的能力换取该点能力,当然也要付出相应的代价,给出该树和“能力售卖点”,求从某个点走到根的最小代价;
分析:
第一眼,树规,直接往上跳有80分。
第二眼,用倍增保存某段上能力最小值可以过完。
具体来说就是对于每个出发点都必须在那里买一张票,f[i][j]就存从包括i点的共2的j次方个点出发的最小代价,然后在dfs的同时枚举这个点的方案数,找出在这里买了票能到的点的代价最小值,然后再对于这个点及祖先节点倍增处理,
一个经典的错,f和fa里的第二维一个包括自己一个不包括,我错误地当成了二倍关系。所以模板要多写啊,不然容易犯理所当然的错,毕竟一开始照着模板并没有推敲每一步的正确性。
还有写pow函数的习惯不好,,,下次改成位运算不然容易T QAQ
#include<iostream>
#include<cstdio>
#include<cstring>
#define clr(x) memset(x,0,sizeof(x))
using namespace std;
const int maxn=1e5;
int fr[maxn],tov[maxn],des[maxn],frqua[maxn],tovqua[maxn],w[maxn],k[maxn],fa[maxn*4][20],f[maxn*4][20];
int n,m,v,sta,fin,q;
int read()
{
char tmp[11];
int len,ret=0;clr(tmp);
scanf("%s",tmp);len=strlen(tmp);
for(int i=0;i<len;i++)ret=ret*10+tmp[i]-'0';
return ret;
}
void addedge(int cur)
{
sta=read();fin=read();
tov[cur]=fr[fin];fr[fin]=cur;des[cur]=sta;
fa[sta][0]=fin;
}
void addedge2(int cur)
{
v=read();k[cur]=read();w[cur]=read();
tovqua[cur]=frqua[v];frqua[v]=cur;
}
int poww(int t)
{
int p=1;
for(int i=1;i<=t;i++)p*=2;
return p;
}
void bz(int u)
{
if(u==1)return;
f[u][0]=1e9;
for(int i=frqua[u];i;i=tovqua[i]){
int tmp=k[i],tmp3=fa[u][0],tmp2=f[tmp3][0];
for(int j=17;j>=0;j--)if(tmp>=poww(j)){
tmp2=min(tmp2,f[tmp3][j]);
tmp3=fa[tmp3][j];
tmp-=poww(j);
}
f[u][0]=min(f[u][0],tmp2+w[i]);
}
for(int i=1;i<=17;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=1;i<=17;i++)
f[u][i]=min(f[u][i-1],f[fa[u][i-1]][i-1]);
}
void dfs(int u)
{
bz(u);
for(int i=fr[u];i;i=tov[i])
dfs(des[i]);
}
void init()
{
n=read();m=read();
for(int i=1;i<n;i++)addedge(i);
for(int i=1;i<=m;i++)addedge2(i);
dfs(1);
q=read();
}
void work()
{
sta=read();
printf("%d\n",f[sta][0]);
}
int main()
{
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
init();
for(int i=1;i<=q;i++)work();
return 0;
}
T3:
题意:对一个字符串做操作,包括光标左右移,插入删除显示和反转左右光标间的字符。
第一眼:双向链表;
第二眼:标记;
具体来说,就是双线链表支持各种操作,特别的,对于反转操作,要把要反转的两边都改完,反转部分的端点改完,剩下的在操作的时候检验反向就可以了。
还有链表的特色,前两个点一个是开始节点一个是结束节点,只有这样才好判断这样也很巧妙!
开始写之前一定要把这种细节想清楚不然敲键盘效率会很低!
还有就是要学会抓住问题的关键,这里的左右光标居然把我难倒了明明可以用一种方法表示。
再谈一谈常数的问题:
不改inline,getchar()过不完,改了也没过完,再改一个show()里的putchar()变成了0.8s,改完了putchar()变成了0.4s,某大神位运算0.3s,这里就是常数,至少十倍。
代码风格真的很重要,尤其是大数据输入输出,inline和位运算,不仅让代码好看,还快很多啊。
顺便,思路理清楚以后,虽然代码130+行,写起来很快很清晰,这就是磨刀不误砍柴工啊。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=8e6+5;
int suf[maxn],pre[maxn],pos[2],cnt[2],n,len,idx,m;
char ch[maxn],c,w,add,tmp[maxn/2];
void init()
{
scanf("%s",tmp);len=strlen(tmp);
pos[0]=pos[1]=cnt[0]=cnt[1]=1;
pre[1]=-1;suf[1]=2;
pre[2]=1;suf[2]=-1;
idx=2;
for(int i=0;i<len;i++){
ch[++idx]=tmp[i];
pre[idx]=i==0?1:idx-1;
suf[idx]=i==len-1?2:idx+1;
}
if(len>0){
pos[1]=idx;cnt[1]=idx+1;
suf[1]=3;
pre[2]=idx;
}
scanf("%d",&m);
}
inline int dir()
{
getchar();w=getchar();
return w=='L'?0:1;
}
inline void movelef(int opt)
{
if(pos[opt]==1)putchar('F');
else{
int u=pos[opt],v=pre[u];
if(u!=suf[v])swap(pre[v],suf[v]);
pos[opt]=v;
cnt[opt]--;
putchar('T');
}
putchar('\n');
}
inline void moverig(int opt)
{
if(suf[pos[opt]]==2)putchar('F');
else{
int u=suf[pos[opt]],v=suf[u];
if(pre[v]!=u)swap(pre[v],suf[v]);
pos[opt]=u;
cnt[opt]++;
putchar('T');
}
putchar('\n');
}
inline void inser(int opt)
{
getchar();add=getchar();
int u=pos[opt],v=suf[pos[opt]];
ch[++idx]=add;
pre[idx]=pos[opt];
suf[idx]=v;
pre[v]=idx;
suf[u]=idx;
pos[opt]=idx;
//if(cnt[opt^1]==cnt[opt])pos[opt^1]=idx;
if(pos[opt^1]==u)pos[opt^1]=idx;
if(cnt[opt^1]>=cnt[opt])cnt[opt^1]++;
cnt[opt]++;
putchar('T');
putchar('\n');
}
inline void del(int opt)
{
if(suf[pos[opt]]==2)putchar('F');
else{
int u=suf[pos[opt]],v=suf[u];
if(pre[v]!=u)swap(pre[v],suf[v]);
suf[pos[opt]]=v;
pre[v]=pos[opt];
if(pos[opt^1]==u)pos[opt^1]=v;//关联;
if(cnt[opt^1]>cnt[opt])
cnt[opt^1]--;
putchar('T');
}
putchar('\n');
}
inline void rever()
{
if(cnt[1]-cnt[0]<=0)putchar('F');//读题;
else {
if(cnt[1]-cnt[0]>1){
int a=pos[0],b=suf[a],c=pos[1],d=suf[c];
swap(suf[b],pre[b]);swap(suf[c],pre[c]);
suf[a]=c;pre[c]=a;
suf[b]=d;pre[d]=b;
pos[1]=b;
}
putchar('T');
}
putchar('\n');
}
inline void showin()
{
int u=1;
while(true){
if(pre[suf[u]]!=u)swap(suf[suf[u]],pre[suf[u]]);
u=suf[u];
if(u==2)break;
putchar(ch[u]);
}
putchar('\n');
}
void work()
{
for(int i=1;i<=m;i++){
getchar();
c=getchar();
if(c=='<')movelef(dir());
else if(c=='>')moverig(dir());
else if(c=='I')inser(dir());
else if(c=='D')del(dir());
else if(c=='R')rever();
else showin();
}
}
int main()
{
freopen("editor.in","r",stdin);
freopen("editor.out","w",stdout);
init();
work();
}