您的位置:首页 > 其它

ACM-9月24日周日周末训练心得

2017-09-24 21:41 239 查看
    这周又是两场网络赛,周六的北京赛区实在是战况惨烈,只出了第一道题,签了个到,第一题是我写的= =,队友们全部卡在后面的题目了,第一题大致的意思就是小明旅游n天有m天呆在北京,m天中的第一天去北大,剩下的天里再找一天去北大,然而每天在北大排队的人数不同,求总排队人数最少的天,而且有些天是交通管制哪里都不能去,所以要花k天在北京减去交通管制的天数正好是m天,我的做法就是用循环去遍历,交通管制的那天我自动将排队人数变成-1处理。

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int n,m,q,r,min,resr,resl,cnt;
int p[100];
while(scanf("%d%d",&n,&m)!=EOF)
{
min=2001;
for(int i=0;i<n;i++)
{
scanf("%d",&p[i]);
}
scanf("%d",&q);
for(int i=0;i<q;i++)
{
scanf("%d",&r);
p[r]=-1;
}
for(int k=m;k<=n;k++)
{
for(int i=0;i<=n-k;i++)
{
cnt=0;
if(p[i]==-1)continue;
for(int j=i+1;j<=i+k-1;j++)
{
if(p[j]==-1)cnt++;
}
if(k-cnt==m)
{
for(int j=i+1;j<=i+k-1;j++)
{
if(p[i]+p[j]<=min&&p[j]!=-1){min=p[i]+p[j];resr=i;resl=j;}
}
}
else continue;
}
}
printf("%d %d\n",resr,resl);
}
}    然后今天的南宁赛区的网络赛,A了两道题,怎么说呢,线段树和树状数组如果再看的多一点的话可能能写更多,在此,谴责自己。
    A的第一道题是B,这道题算的是列车上最大的乘客位数,一开始用的线段树,由于对更新线段树的掌握还不是很透彻,发现把问题想复杂了,最后改为暴力就过了

#include<string.h>
#include<math.h>
#include<vector>
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
int x;
int val;
int cnt;
}a[2005];
bool cmp(node qq,node ww)
{
if(qq.x==ww.x)
{
return qq.cnt>ww.cnt;
}
return qq.x<ww.x;
}
int main()
{
int n;
while(scanf("%d",&n))
{
if(n==0) {cout<<"*"<<endl;break;}
int o=0;
for(int i=1;i<=n;i++)
{
int h,h1,h2;
scanf("%d%d%d",&h1,&h2,&h);
if(h1>h2) swap(h1,h2);
if(h1==h2) continue;
a[++o].x=h1;
a[o].val=h;
a[o].cnt=1;

a[++o].x=h2-1;
a[o].val=h;
a[o].cnt=-1;
}
sort(a+1,a+o+1,cmp);
int sum=0,ans=0;
for(int i=1;i<=o;i++)
{
if(a[i].cnt==1) sum+=a[i].val;
if(a[i].cnt==-1) sum-=a[i].val;
if(sum>ans) ans=sum;
}
cout<<ans<<endl;
}
}    第二个是完全套用的线段树扫描的模板,极其类似,然后就过了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=10005;
#define lson i*2,l,m
#define rson i*2+1,m+1,r
#define root 1,1,k-1
int X[MAXN];
struct node
{
int l,r,h;
int d;
node(){}
node(int a,int b,int c,int d): l(a),r(b),h(c),d(d){}
bool operator <(const node &b)const
{
return h<b.h;
}
}nodes[MAXN];
int cnt[MAXN*4];
int sum[MAXN*4];
void PushDown(int i,int l,int r)
{
int m=(l+r)/2;
if(cnt[i]!=-1)
{
cnt[i*2]=cnt[i*2+1]=cnt[i];
sum[i*2]= (cnt[i]?(X[m+1]-X[l]):0) ;
sum[i*2+1]= (cnt[i]?(X[r+1]-X[m+1]):0) ;
}
}
void PushUp(int i,int l,int r)
{
if(cnt[i*2]==-1 || cnt[i*2+1]==-1)
cnt[i]=-1;
else if(cnt[i*2]!= cnt[i*2+1])
cnt[i]=-1;
else
cnt[i]=cnt[i*2];
sum[i]=sum[i*2]+sum[i*2+1];
}
void build(int i,int l,int r)
{
if(l==r)
{
cnt[i]=0;
sum[i]=0;
return ;
}
int m=(l+r)/2;
build(lson);
build(rson);
PushUp(i,l,r);
}
void update(int ql,int qr,int v,int i,int l,int r)
{
if(ql<=l && r<=qr)
{
if(cnt[i]!=-1)
{
cnt[i]+=v;
sum[i] = (cnt[i]? (X[r+1]-X[l]):0);
return ;
}
}
PushDown(i,l,r);
int m=(l+r)/2;
if(ql<=m) update(ql,qr,v,lson);
if(m<qr) update(ql,qr,v,rson);
PushUp(i,l,r);
}
int bin(int key,int n,int d[])
{
int l=1,r=n;
while(r>=l)
{
int m=(r+l)/2;
if(d[m]==key)
return m;
else if(d[m]>key)
r=m-1;
else
l=m+1;
}
return -1;
}
int main()
{
int q;
int kase=0;
while(scanf("%d",&q))
{
if(q==0){cout<<"*"<<endl;break;}
int n=0,m=0;
for(int i=1;i<=q;i++)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
X[++n]=x1;
nodes[++m]=node(x1,x2,y1,1);
X[++n]=x2;
nodes[++m]=node(x1,x2,y2,-1);
}
sort(X+1,X+n+1);
sort(nodes+1,nodes+m+1);
int k=1;//共k个不同的x坐标,组成了k-1个不同的区域
for(int i=2;i<=n;i++)
if(X[i]!=X[i-1]) X[++k]=X[i];
build(1,1,k-1);//少了build就WA
int ret=0;//最终面积
for(int i=1;i<m;i++)
{
int l=bin(nodes[i].l,k,X);
int r=bin(nodes[i].r,k,X)-1;
if(l<=r) update(l,r,nodes[i].d,root);
ret += sum[1]*(nodes[i+1].h-nodes[i].h);
}
cout<<ret<<endl;
}
}
    比较可惜的是第L题,用的动态规划,求最重的上升子序列,最后是以内存超了为结束,想不到如何解决。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<cmath>
#include<vector>
using namespace std;
int main()
{
int dp[200001],c,maxw,q=0;
char l;
vector<int> a,w;
while(scanf("%d",&c))
{
if(c<0)
{
a.push_back(c);
w.push_back(0);
}
else if(c>=10000)
{
a.push_back(c-10000);
w.push_back(5);
}
else
{
a.push_back(c);
w.push_back(1);
}
l=getchar();
if(l=='\n')break;
}
int n=a.size();
//cout<<n<<endl<<endl;
dp[0]=w[0];//表示以w[0]为子序列最右边的重量
for (int i=1;i<n;i++)
{
dp[i]=w[i];
for (int j=0;j<i;j++)
{
if (a[i]>=a[j]&&dp[j]+w[i]>dp[i])
dp[i]=dp[j]+w[i];
}
}
for(int i=maxw=0;i<n;i++)
{
maxw=max(maxw,dp[i]);
//cout<<dp[i]<<endl;
}
cout<<maxw<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: