前几天把上次考试的题补得差不多了。差最后一题,貌似加上离散化后把原题写炸了,始终没有A掉。等集训一段时间在回头看这题吧。
正好暑期集训即将开始,感觉已经在家咸鱼了一个星期,再不做题怕是要爆零了。。。
------------------------------------------------------------------------------------------------------------------------------------------------------------
8月5日更新:最后一题已经AC了~,又干了3个小时。。。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
A题(智能停车场)(xdoj1334)
模拟,可以按车辆到达时间排个序,然后对于每辆车,直接照车位就可以了。
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef struct
{
int s;
int e;
int ind;
int w;
} Car;
Car p[1010];
Car st[10100];
bool cmp1(Car x,Car y)
{
if(x.s!=y.s)
return x.s=st[j].e)
{
ind=j;
break;
}
}
p[i].w=ind;
st[ind].e=p[i].e;
}
sort(p+1,p+n+1,cmp2);
printf("%d",p[1].w);
for(int i=2;i<=n;i++)
printf(" %d",p[i].w);
return 0;
}
B题(珂朵莉,威廉和第七兽)(xdoj1327)
直接暴搜,签到题。
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
char maze[55][55];
int mp[55][55];
int vis[55][55];
int c1,c2,c3,c4=0;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
int n,m;
void dfs(int x,int y,int num)
{
for(int i=0;i<=4;i++)
{
int tx=x+dx[i];
int ty=y+dy[i];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&mp[tx][ty]==num&&!vis[tx][ty])
{
vis[tx][ty]=1;
dfs(tx,ty,num);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
getchar();
for(int i=1;i<=n;i++)
{
scanf("%s",maze[i]);
getchar();
}
for(int i=1;i<=n;i++)
{
for(int j=0;j
C题(拿石头的游戏)(xdoj1328)
白书上模板题-硬币游戏
相信学过博弈论后大家对这道题有了刚深入的理解。。。
代码:
#include
using namespace std;
int X,K,A[110];
bool win[10010];
void solve()
{
win[0]=false;
for(int j=1;j<=X;j++)
{
win[j]=false;
for(int i=0;i
D题(忙碌的周末)(xdoj1333)
CF上原题,这道题关键在于推出这个集合中最多有三个数,分类讨论即可
代码(写的有点丑):
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
E题( 珂朵莉、威廉和第十一兽 )
这道题直接bfs即可,不过需要注意一些特殊情况,特判一下。
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef struct
{
int x;
int y;
int c;
int s;
} P;
int mp[110][110];
int vis[110][110];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
char mmp[110][110];
int n,m,t,tx,ty,fx,fy;
int bfs()
{
queue q;
P t1;
t1.c=mp[fx][fy];
t1.s=0;
t1.x=fx;
t1.y=fy;
q.push(t1);
while(!q.empty())
{
P tt=q.front();
q.pop();
if(tt.x==tx&&tt.y==ty)
return tt.s;
for(int i=0;i<4;i++)
{
int nx=tt.x+dx[i];
int ny=tt.y+dy[i];
int pan=(tt.c+1)%t;
if(pan==0)
pan=t;
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]==pan&&!vis[nx][ny])
{
P t2;
vis[nx][ny]=1;
t2.x=nx;
t2.y=ny;
t2.c=mp[nx][ny];
t2.s=tt.s+1;
q.push(t2);
}
}
}
return -1;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&t)!=EOF)
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
scanf("%s",mmp[i]);
}
for(int i=1;i<=n;i++)
{
for(int j=0;j
F题(生命仪式)(xdoj1326)
区间dp,可参考NOIP原题-能量项链,套路是一样的。不过为什么用之前软院新生赛的标程会T掉呢?(滑稽)
代码:
#include
using namespace std;
typedef long long ll;
ll dp[810][810];
ll a[810];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
a[n+i]=a[i];
}
for(int j=2;j<=2*n;j++)
{
for(int i=j-1;i>0&&j-i
G题(上海上海上海上海蓬莱蓬莱蓬莱蓬莱 ) (xdoj1329)
听之前想了很长时间也不会,听后秒懂系列。
把B当成-1,把R当成1,维护前缀和,再O(n)扫描一遍即可。
代码:
#include
using namespace std;
char s[1100000];
int a[1100000];
int sum[1100000];
int rec[1100000];
int flag[1100000];
int main()
{
while(scanf("%s",s)!=EOF)
{
int len=strlen(s);
memset(rec,0,sizeof(rec));
memset(flag,0,sizeof(flag));
for(int i=0;i
H题(天才琪露诺的完美算数教室 ) (xdoj1330)
打表异或前缀和找规律,这里直接用的题解的思路了,又特判一下0,1,2。不过这道题感觉还没有完全弄懂的样子。。。
代码:
#include
using namespace std;
typedef long long ll;
int main()
{
ll t,n;
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
if(n==0)
{
printf("4 7\n");
}
else if(n==1)
{
printf("1 5\n");
}
else if(n==2)
{
printf("3 5\n");
}
else
{
if(n%4==0)
{
printf("%d %lld\n",1,n);
}
else if(n%4==1)
{
printf("%d %lld\n",2,n-1);
}
else if(n%4==2)
{
printf("%d %lld\n",2,n);
}
else
{
printf("%d %lld\n",1,n-1);
}
}
}
return 0;
}
I题(区间第K大)(xdoj1336)
最开始想写二分+BIT,T掉了,而且也有些复杂。后来发现这道题满足区间递增性,用二分加尺取,直接过了。
大致思路就是每次二分时看比这个区间严格大的有多少个,如果这个数比K小就更新答案,不断逼近答案,最后得出解。
代码:
#include
using namespace std;
typedef long long ll;
ll tem[100005];
ll sum[100005];
int n,k;
ll cal(ll mid)
{
int r=1;
ll res=0;
for(int i=0;i>1;
if (cal(mid)>=k)
l=mid+1;
else
{
r=mid-1;
ans=mid;
}
}
printf("%lld\n",ans);
return 0;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------
J题 火聚聚铺地毯(xdoj1324)
这道题可以说是poj3171和poj2528的一个结合版,难度加大了不少,在上次比赛中出现在最后一题的位置(不过有几位聚聚做出来了,膜)。首先总体上dp的思路是好想的,可以设dp[i]为到 i 位置的最小花费,易得dp[i]=min(dp[j])+c[i].w;(a[i].l-1<=j<=a[i].r)。可是这么算复杂度是O(n^2),要超时的。因为是区间查询最值问题,想到线段树。用Minv数组维护dp数组,每次查询之前区间的最小值为log(sum),sum为地毯总长度,不过这道题sum过大,线段树存不下,考虑离散化。这道题还需要考虑相邻两个点之间离散化后若相邻,需判断原来两个点是否直接相邻,若不,再中间加一个点(详见代码)。此时sum最高为400000左右,总复杂度nlog(sum), 刚刚好。
代码:
#include
#include
#include
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
typedef long long ll;
const int maxn = 400010;
int Min[maxn<<2];
void PushUP(int rt) {
Min[rt] = min(Min[rt<<1] , Min[rt<<1|1]);
}
typedef struct
{
ll li;
ll ri;
int w;
} Cloth;
Cloth c[100010];
Cloth ccopy[100010];
ll lisan[400040];
bool cmp(Cloth x,Cloth y)
{
if(x.li!=y.li)
return x.li> 1;
build(lson);
build(rson);
}
void update(int p,int sc,int l,int r,int rt) {
if (l == r) {
Min[rt] = min(Min[rt],sc);
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(p , sc , lson);
else update(p , sc , rson);
PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
return Min[rt];
}
int m = (l + r) >> 1;
int ret = 2e9;
if (L <= m) ret = min(ret , query(L , R , lson));
if (R > m) ret = min(ret , query(L , R , rson));
return ret;
}
int main()
{
int n;
ll m,e;
scanf("%d%lld%lld",&n,&m,&e);
for(int i=0;i1)
{
lisan[num++]=lisan[i-1]+1;
}
}
sort(lisan,lisan+num);
ll mm = lower_bound(lisan,lisan+num,m)-lisan;
mm++;
ll ee = lower_bound(lisan,lisan+num,e)-lisan;
ee++;
for(int i=0;icur+1)
{
flag=0;
break;
}
int tem=query(c[i].li-1,c[i].ri,mm-1,ee,1);
update(c[i].ri,tem+c[i].w,mm-1,ee,1);
cur=max(cur,ccopy[i].ri);
}
if(e > cur)
{
printf("-1\n");
return 0;
}
if(flag)
printf("%d\n",query(ee,ee,mm-1,ee,1));
else
printf("-1\n");
return 0;
}