T1
模拟题,没什么可以说的。。。
直接暴力找就可以。。。唯一A掉的题
但是std写的比我少很多。。。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
int wpcnt,wgcnt,t1,t2;
unsigned short int mapp[4][4],apr[27];
bool winp[27],wing[27][27];
//先看两条对角线,然后看列、行
void clr()
{
memset(apr,0,sizeof apr);
}
void judge1(int x,int y)//个人获胜
{
//cout<<x<<' '<<y<<' '<<mapp[x][y]<<' '<<winp[mapp[x][y]]<<'\n';
if(!winp[mapp[x][y]])
{
winp[mapp[x][y]]=1;
++wpcnt;
}
}
void judge2()//团队获胜
{
if(!wing[t1][t2])
{
wing[t1][t2]=1;
wing[t2][t1]=1;
++wgcnt;
}
}
short int judge(short int x,short int y)
{
if(apr[mapp[x][y]]==3)
return 1;
if(apr[mapp[x][y]]==2)
return 2;
return 0;
}
int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
int temp;
char c;
For(i,1,3)
For(j,1,3)
{
while((c=getchar())==' '||c=='\n'||c=='\r');
mapp[i][j]=c-'A'+1;
}
//右斜对角线
For(i,1,3)
{
apr[mapp[i][i]]++;
}
temp=judge(1,1);
if(temp==1)
{
judge1(1,1);
}
else if(!temp)
temp=judge(2,2);
if(temp==2)
{
For(i,1,3)
{
if(apr[mapp[i][i]]==1)
t2=mapp[i][i];
else
t1=mapp[i][i];
}
judge2();
}
//cout<<temp<<'\n';
clr();
//左斜对角线
for(int i=1;i<=3;++i)
apr[mapp[i][4-i]]++;
temp=judge(1,3);
if(temp==1)
{
judge1(1,3);
}
else if(!temp)
temp=judge(2,2);
if(temp==2)
{
For(i,1,3)
{
if(apr[mapp[i][4-i]]==1)
t2=mapp[i][4-i];
else
t1=mapp[i][4-i];
}
judge2();
}
//行
For(i,1,3)
{
clr();
For(j,1,3)
{
apr[mapp[i][j]]++;
}
temp=judge(i,1);
if(temp==1)
{
judge1(i,1);
}
else if(!temp)
temp=judge(i,2);
if(temp==2)
{
For(j,1,3)
{
if(apr[mapp[i][j]]==1)
t2=mapp[i][j];
else
t1=mapp[i][j];
}
judge2();
}
}
//列
For(i,1,3)
{
clr();
For(j,1,3)
apr[mapp[j][i]]++;
temp=judge(1,i);
if(temp==1)
{
judge1(1,i);
}
else if(!temp)
temp=judge(2,i);
if(temp==2)
{
For(j,1,3)
{
if(apr[mapp[j][i]]==1)
t2=mapp[j][i];
else
t1=mapp[j][i];
}
judge2();
}
}
cout<<wpcnt<<'\n'<<wgcnt;
return 0;
}
T2
一个贪心题目,想法比较简单,显然我们需要把更多的时间留给高处的ci大的景点,sort一遍然后递推来做就可以
但是
一定要开long long
我想省一下空间结果弄巧成拙丢了50分- -(不然就不用去买耳机了,真让人难过)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
inline long long int read()
{
char c;
bool t=0;
long long int a=0;
while((c=getchar())==' '||c=='\n'||c=='\r');
if(c=='-')
{
t=1;
c=getchar();
}
while(isdigit(c))
{
a*=10;
a+=(c-'0');
c=getchar();
}
return a*(t?-1:1);
}
struct point{
long long int x,c;
}jd[100001];
bool cmp(point a,point b)
{
return a.c>b.c?1:0;
}
long long int l,n,va,vb,temp;
long long ans;
int main()
{
freopen("max.in","r",stdin);
freopen("max.out","w",stdout);
long long int nowh=0,preh=0;
l=read();
n=read();
va=read();
vb=read();
temp=va-vb;
For(i,1,n)
{
jd[i].x=read();
jd[i].c=read();
}
sort(jd+1,jd+n+1,cmp);
For(i,1,n)
{
if(nowh<jd[i].x)
{
preh=nowh;
nowh=jd[i].x;
ans+=(temp*(nowh-preh)*jd[i].c);
}
}
printf("%lld",ans);
return 0;
}
T3
一个比较难的动态规划题
但是考试的时候居然理解成重叠部分了。。。然后就看了两个小时,不然怎么也能拿30分搜索分。。。
以后还是要认真读题。。。
讲个思路吧。。。
先按左端点排序
既然是并集,那么我们就一定不会选那些被其他线段包含掉的小线段,所以我们先把那些被包含掉的线段都删掉,代码实现玄学
然后我们以线段序号数和用了的线段数为状态来dp
dp[i][k]=dp[j][k-1]+__________
去掉后剩下的线段就是这种情况
这样看有两种情况
一种是一条和另一条有交集,另一种就是没有交集
①对于像(2,3)这种有重叠部分的线段,我们的状态转移方程是
dp[i][k]=dp[j][k-1]+r[i]-r[j]
②对于(1,3)这种没有重叠的,我们的状态转移方程是
dp[i][k]=dp[j][k-1]+r[i]-l[i]
显然,对于确定的i,k,r[i] 和 l[i]是不会变的,我们要做的只是找出
dp[j][k-1]和dp[j][k-1]-r[j]的最大值
可以预处理出最大值,然后直接调用
暴力不预处理的话单次寻找是O(n),全部状态O(nk)
所以复杂度是O(k n^2)
优化一下可以做到O(k n log n)
然后说可以用单调队列来优化。。。但是没有讲。。。