poj 3672
改了许久主要是 区间更新时的范围有弄错了。。
还有 l,r 写反了。。。。
每回线段树都要调很久怎么破。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
//by mars_ch
struct data
{
int l,r;
int lsum,rsum,sum;
int cover;
}line[50005*8];
void build(int l,int r,int num)
{
line[num].cover=-1;
line[num].lsum=line[num].rsum=line[num].sum=r-l+1;
if(l == r) return;
int mid=(l+r)/2;
build(l,mid,num*2);
build(mid+1,r,num*2+1);
}
void pushdown(int num,int k)
{
if(line[num].cover!=-1)
{
line[num*2].cover=line[num*2+1].cover=line[num].cover;
line[num*2].lsum=line[num*2].rsum=line[num*2].sum=line[num].cover?0:k-(k/2);//左子树的前半部分和后半部分
line[num*2+1].lsum=line[num*2+1].rsum=line[num*2+1].sum=line[num].cover?0:(k/2);
line[num].cover=-1;
}
}
void pushup(int num,int k)
{
line[num].lsum=line[num*2].lsum;
line[num].rsum=line[num*2+1].rsum;
if (line[num].lsum == k-k/2)
line[num].lsum += line[num*2+1].lsum;
if (line[num].rsum == k/2)
line[num].rsum += line[num*2].rsum;
line[num].sum = max(line[num*2].rsum+line[num*2+1].lsum, max(line[num*2].sum, line[num*2+1].sum));
}
void updata(int l,int r,int L,int R,int num,int op)
{
//printf("first %d %d %d %d\n",l,r,L,R);
if(l<=L && r>=R)
{
line[num].lsum=line[num].rsum=line[num].sum=op?0:R-L+1;
line[num].cover=op;
return;
}
pushdown(num,R-L+1);
//printf("second %d %d\n",l,r);
int mid=(L+R)/2;
if(l<=mid) updata(l,r,L,mid,num*2,op);
if(r>mid) updata(l,r,mid+1,R,num*2+1,op);
//printf("third %d %d\n",l,r);
pushup(num,R-L+1);
}
int query(int x,int l,int r,int num)
{
if(l ==r ) return 1;
pushdown(num,r-l+1);
int mid=(l+r)/2;
if(line[num*2].sum>=x)
{
return query(x,l,mid,num*2);
}
else if(line[num*2].rsum+line[num*2+1].lsum>=x)
{
return mid-line[num*2].rsum+1;
}
else
{
return query(x,mid+1,r,num*2+1);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1);
for(int i=1;i<=m;i++)
{
int op;
scanf("%d",&op);
if(op == 1)
{
int a;
scanf("%d",&a);
if(line[1].sum<a) printf("0\n");
else
{
int pos=query(a,1,n,1);
printf("%d\n",pos);
updata(pos,pos+a-1,1,n,1,1);
/*for(int i=1;i<=25;i++)
{
printf("%d %d %d\n",line[i].sum,line[i].lsum,line[i].rsum);
} */
}
}
else
{
int a,b;
scanf("%d%d",&a,&b);
/*for(int i=1;i<=25;i++)
{
printf("%d %d %d\n",line[i].sum,line[i].lsum,line[i].rsum);
} */
updata(a,a+b-1,1,n,1,0);
/*for(int i=1;i<=25;i++)
{
printf("%d %d %d\n",line[i].sum,line[i].lsum,line[i].rsum);
} */
}
}
}
poj 3666
一道dp题,最近dp差得要疯掉。
打算刷刷题。
这道 不知道为什么,知道状态转移怎么写。但是总是觉得不对劲
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
//by mars_ch
long long dp[2001][2001];
int a[2001];
int b[2001];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
for(int i=1;i<=n;i++)
{
long long mn=dp[i-1][1];
for(int j=1;j<=n;j++)
{
mn=min(mn,dp[i-1][j]);
dp[i][j]=mn+abs(a[i]-b[j]);
}
}
long long ans=0x3fffffff;
for(int i=1;i<=n;i++)
{
ans=min(ans,dp[n][i]);
}
printf("%lld\n",ans);
}
poj 3669
一道bfs没啥好说的 但是打算优化一下常数。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
//by mars_ch
int dx[5]={0,0,1,-1};
int dy[5]={1,-1,0,0};
int time[305][305];
int dis[305][305];
int vis[305][305];
int n;
queue<pair<int,int> >q;
void minn(int x,int y,int t)
{
if(time[x][y]!=-1)
{
time[x][y]=min(time[x][y],t);
}
else time[x][y]=t;
}
int main()
{
memset(time,-1,sizeof(time));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x,y,t;
scanf("%d%d%d",&x,&y,&t);
minn(x,y,t);
if(x-1>=0) minn(x-1,y,t);
minn(x+1,y,t);
if(y-1>=0) minn(x,y-1,t);
minn(x,y+1,t);
}
/*for(int i=0;i<=4;i++)
{
for(int j=0;j<=4;j++)
{
printf("%d ",time[i][j]);
}
puts("");
}*/
q.push(make_pair(0,0));
vis[0][0]=1;
while(!q.empty())
{
pair<int,int> P=q.front();
q.pop();
int x=P.first,y=P.second;
//printf("%d %d %d\n",x,y,time[x][y]);
if(time[x][y] == -1)
{
printf("%d\n",dis[x][y]);
return 0;
}
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(vis[nx][ny]) continue;
if(nx<0 || ny<0 || ny>=304 || nx>=304) continue;
if((time[nx][ny]<=dis[x][y]+1) && time[nx][ny]!=-1)
{
vis[nx][ny]=1;
continue;
}
dis[nx][ny]=dis[x][y]+1;
vis[nx][ny]=1;
q.push(make_pair(nx,ny));
}
}
printf("%d\n",-1);
}
poj 3672
一直以为要输出最远走多少。zz
原来是方案数。
提醒我们不要看错题。
orz看错就真的跪了。
#include <iostream>
#include <string>
using namespace std;
char unit[100005];
int main()
{
int m, t, u, f, d, i, ans = 0, sum = 0;
cin >> m >> t >> u >> f >> d;
for (i = 0; i < t; i++)
cin >> unit[i];
for (i = 0; i < t; i++)
{
if (unit[i] == 'u')
{
sum += u + d;
ans++;
}
else if (unit[i] == 'f')
{
sum += f + f;
ans++;
}
else if (unit[i] == 'd')
{
sum += d + u;
ans++;
}
if (sum > m)
{
cout << ans-1 << endl;
break;
}
}
}
poj 3671 类似啊
#include<cstdio>
#include<algorithm>
#include<cstring>
//by mars_ch
using namespace std;
int n;
int a[30005];
int dp[30005][3];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int minn=0x3fffffff;
dp[1][1]=1,dp[1][2]=1;
dp[1][a[1]]=0;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=2;j++)
{
minn=0x3fffffff;
for(int k=1;k<=j;k++)
{
minn=min(minn,dp[i-1][k]);
}
if(a[i] == j) dp[i][j]=minn;
else dp[i][j]=minn+1;
}
}
printf("%d\n",min(dp[n][1],dp[n][2]));
return 0;
}