CSPS模拟75&76
感觉自己还是太菜了。。。
最近考试一直想不出来正解。难受(然而蒟蒻的博客没人看也要不来小猪peiqi的图)
模拟75:血炸。。。
考场上推了快两个小时的T1式子,然后心态炸裂,然后我也不知道自己干了什么,反正T1瞎打了一发,没过小样例
然后康T3,qj了部分分,不会打暴力,瞎码了一发,没过小样例。然后赶紧开T2,然后码了半天读入然后qj掉部分分
然后就没有然后了,然后考试就结束了,然后我就垫底了。然后改题该了一天。。。
注意考试时间和考试心态,不能慌
题确实挺好
T1:正解为凸包,然后卡精,把输入的a和b取倒数得到z=Ax+By,然后维护一个左下凸包就可以了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define N 300050
//#define double long double
using namespace std;
const double eps=;
vector<int>v[N];
struct node{int a,b,id;}q[N];
bool cmp(const node &x,const node &y)
{
return x.a==y.a?x.b>y.b:x.a>y.a;
}
inline int read()
{
int s=;char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')s=s*+c-'',c=getchar();
return s;
}
bool check(double a,double b)
{
double k;
if(a>b)k=a-b;
else k=b-a;
return b<eps;
}
inline double work1(double x1,double x2,double x3,double y1,double y2,double y3)
{
return (y1-y2)*(x3-x2)/y2/y1/x2/x3;
}
inline double work2(double x1,double x2,double x3,double y1,double y2,double y3)
{
return (x2-x1)*(y2-y3)/y2/y3/x2/x1;
}
int n;
int ans[N];
priority_queue<int>qq;
int d[N],ba;
int main()
{
// freopen("da.in","r",stdin);
n=read();
for(int i=;i<=n;++i)
{
q[i].a=read();
q[i].b=read();
q[i].id=i;
}
sort(q+,q+n+,cmp);
int ma2=,ma1=;
for(int i=;i<=n;++i)
{
if(q[i].b>ma2)
{
ma2=q[i].b;ma1=q[i].a;
ans[++ans[]]=i;
}
else if(q[i].b==ma2)
{
if(ma1==q[i].a)ans[++ans[]]=i;
}
}
for(int i=,t,p;i<=ans[];++i)
{
double a1,a2,a3,b1,b2,b3;
double x1,x2,x3,y1,y2,y3;
t=ans[i];
a1=1.0/q[t].a;b1=1.0/q[t].b;
x1=q[t].a;y1=q[t].b;
if(!ba){
d[++ba]=t;
continue;
}
while(ba>)
{
a2=1.0/q[d[ba]].a;
b2=1.0/q[d[ba]].b;
x2=q[d[ba]].a;y2=q[d[ba]].b;
if(a1>a2&&b1>b2)break;
if(x1==x2&&y1==y2){v[d[ba]].push_back(q[t].id);break;}
a3=1.0/q[d[ba-]].a;
b3=1.0/q[d[ba-]].b;
x3=q[d[ba-]].a;y3=q[d[ba-]].b;
if(check(work1(x1,x2,x3,y1,y2,y3),work2(x1,x2,x3,y1,y2,y3)))
{
d[++ba]=t;break;
}
if(work1(x1,x2,x3,y1,y2,y3)-work2(x1,x2,x3,y1,y2,y3)>eps)
{
--ba;
}
else
{
d[++ba]=t;break;
}
}
if(ba==)
{
d[++ba]=t;
}
}
for(int i=;i<=ba;++i)
{
qq.push(-q[d[i]].id);
for(int j=;j<v[d[i]].size();++j)
{
qq.push(-v[d[i]][j]);
}
} while(!qq.empty()){
printf("%d ",-qq.top());
qq.pop();
}
return ;
}
T2:注意输入。。。正解为Gauss消元,把答案矩阵的系数消掉,则最后等式右面就是答案的相反数
证明为啥可以直接进行高斯消元,首先答案行可以表示为每个已知行乘以一个系数相加得到。那么感性理解一下,考虑每个已知方程的贡献,当它下传时,下面的方程其实已经
累积了该方程的贡献,而题目又保证有解,所以考虑完每个方程后最后答案方程的系数一定会被消完
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define N 300
#define ull unsigned long long
using namespace std;
int n;
ull p=;
ull po[N];
ull lsh[];
int ls;
int a[N];
int pd[N];
double c[N][N],cc[N];
struct node{
ull ha;
int t;
double x;
}b[N][N];
void init()
{
sort(lsh+,lsh+ls+);
ls=unique(lsh+,lsh+ls+)-lsh-;
for(int i=;i<=n;++i)
{
for(int j=;j<a[i];++j)
{
b[i][j].t=lower_bound(lsh+,lsh+ls+,b[i][j].ha)-lsh;
c[i][b[i][j].t]=b[i][j].x;
}
cc[i]=b[i][a[i]].x;
}
cc[n]=;
}
double ks[N];
void pr()
{
for(int i=;i<=n;++i)
{
for(int j=;j<=ls;++j)
printf("%.1lf ",c[i][j]);
printf("%.1lf\n",cc[i]);
}
puts("");
}
void Gauss()
{
const int nn=n-;
int ts=;
// pr();
//while(1)
for(int o=;o<=;++o)
{
for(int i=,t;i<=ls&&ts<n;++i)
{
if(!c[n][i])continue;
t=ts;
for(int j=t+;j<n;++j){
if(fabs(c[j][i])>fabs(c[t][i])){
// printf("i:%d j::::%d\n",i,j);
for(int k=;k<=ls;++k)
swap(c[t][k],c[j][k]);
swap(cc[t],cc[j]);
}
}
if(!c[t][i])continue;
for(int j=;j<=n;++j)
{
if(!c[j][i]||j==t)continue;
double p=c[j][i]/c[t][i];
for(int k=;k<=ls;++k)
c[j][k]-=c[t][k]*p;
cc[j]-=cc[t]*p;
}
++ts;
// pr();
}
int ok=;
for(int i=;i<=ls;++i){if(c[n][i])ok=;}
if(ok)break;
// pr();
}
if(fabs(cc[n])<0.0000000001){puts("0.0");return;}
printf("%.1lf\n",-cc[n]);
// pr();
}
int main()
{
// freopen("knight2.in","r",stdin);
scanf("%d",&n);++n;
for(int i=,j,pd;i<=n;++i)
{
double x;char c;
j=;pd=;
while(){
++j;
scanf("%lf",&x);
b[i][j].x=x*pd;
c=getchar();
while(c<'A'||c>'Z')c=getchar();
while(c!=' '){
b[i][j].ha=b[i][j].ha*p+c;
c=getchar();
}
lsh[++ls]=b[i][j].ha;
while(c!='='&&c!='+'&&c!='H')c=getchar();
if(c=='=')pd=-;
else if(c=='H')
{
++j;if(i==n)break;
while(c!='=')c=getchar();
scanf("%lf",&b[i][j].x);
break;
}
}
a[i]=j;
}
init();
Gauss();
}
T3:把老司机按照x排序,第一问即为最长上升子序列。
第二问考虑如何构造,发现最优情况下所有的老司机构成森林,扫描到当前老司机,考虑接在哪个lsj后面,
则可以倍增法对符合条件的lsj求lca,顺便维护一下覆盖的链的最值即可。
#include<bits/stdc++.h>
#define N 100050
#define LL long long
using namespace std;
const LL inf=;
int n,k;
LL b[N],c[N];
int dp[N];
struct node{LL x,a;int id;}q[N];
bool cmp(const node &c,const node &d){return c.x<d.x;}
inline int check(const LL t)
{
for(int i=;i<=n;++i)b[i]=q[i].x*+t*q[i].a;
int ret=;c[]=b[];
for(int i=,po;i<=n;++i)
{
if(b[i]>c[ret])
{
c[++ret]=b[i];
continue;
}
if(b[i]<c[]){
c[]=b[i];
}
else{
po=lower_bound(c+,c+ret+,b[i])-c;
c[po]=b[i];
}
}
return ret;
}
int fa[N][],mn[N][];
int rt[N],tot;
int lc[N*],rc[N*],mi[N*];
inline int getmin(const int xx,const int yy)
{
int x=xx,y=yy,mx=xx,my=yy;
for(int i=;~i;--i)
{
if(fa[x][i]==fa[y][i])continue;
mx=min(mx,mn[x][i]);
my=min(my,mn[y][i]);
x=fa[x][i];y=fa[y][i];
}
// printf("xx:%d yy:%d mx:%d my:%d x:%d y:%d\n",xx,yy,mx,my,x,y);
if(mx<my)return xx;
return yy;
}
inline int upd(int x,int y)
{
if(!x||!y)return x|y;
return getmin(x,y);
}
void add(int &g,int l,int r,int pos,int id)
{
if(!g)g=++tot;
if(l==r){mi[g]=id;return;}
const int m=l+r>>;
if(pos<=m)add(lc[g],l,m,pos,id);
else add(rc[g],m+,r,pos,id);
mi[g]=upd(mi[lc[g]],mi[rc[g]]);
}
int ask(int g,int l,int r,int pos)
{
if(!g)return ;
if(r<pos)return mi[g];
if(l>=pos)return ;
const int m=l+r>>;
return upd(ask(lc[g],l,m,pos),ask(rc[g],m+,r,pos));
}
int ks[N];
inline void getans(int ans)
{
const LL t=1ll*ans*ans;
for(int i=;i<=n;++i)c[i]=b[i]=q[i].x*+t*q[i].a;
sort(c+,c+n+);
for(int j=;j<=n;++j)b[j]=lower_bound(c+,c+n+,b[j])-c;
int ret=;c[]=b[];dp[]=;
add(rt[],,n,b[],q[].id);
for(int i=,po;i<=n;++i)
{
if(b[i]>c[ret])
{
c[++ret]=b[i];dp[i]=ret;
fa[q[i].id][]=ask(rt[ret-],,n,b[i]);
mn[q[i].id][]=fa[q[i].id][];
for(int j=;j<=;++j)
{
fa[q[i].id][j]=fa[fa[q[i].id][j-]][j-];
mn[q[i].id][j]=min(mn[q[i].id][j-],mn[fa[q[i].id][j-]][j-]);
}
add(rt[dp[i]],,n,b[i],q[i].id);
}
else
{
if(b[i]<c[])dp[i]=;
else dp[i]=lower_bound(c+,c+ret+,b[i])-c;
c[dp[i]]=b[i];
fa[q[i].id][]=ask(rt[dp[i]-],,n,b[i]);
mn[q[i].id][]=fa[q[i].id][];
for(int j=;j<=;++j)
{
fa[q[i].id][j]=fa[fa[q[i].id][j-]][j-];
mn[q[i].id][j]=min(mn[q[i].id][j-],mn[fa[q[i].id][j-]][j-]);
}
add(rt[dp[i]],,n,b[i],q[i].id);
}
// printf("i:%d b:%lld dp:%d\n",i,b[i],dp[i]);
// printf("%d %d\n",fa[q[i].id][0],q[i].id);
}
int an=;
for(int i=n;i>=;--i)
if(dp[i]==k)an=upd(an,q[i].id);
// printf("an:%d\n",an);
// an=5;
while(an){
ks[++ks[]]=an;
an=fa[an][];
}
sort(ks+,ks+ks[]+);
for(int i=;i<=ks[];++i)
{
printf("%d\n",ks[i]);
}
}
int main()
{
// freopen("da.in","r",stdin);
//freopen("my.out","w",stdout);
scanf("%d%d",&n,&k);
if(k==){puts("86400\n-1\n");return ;}
for(int i=;i<=n;++i)
scanf("%lld%lld",&q[i].x,&q[i].a),q[i].id=i;
sort(q+,q+n+,cmp);
int l=,r=+,mid;
while(l+<r)
{
mid=l+r>>;
if(check(1ll*mid*mid)>=k)l=mid;
else r=mid;
}
cout<<l<<endl;
// cout<<check(1ll*l*l)<<endl;
if(check(1ll*l*l)>k+){puts("-1");return ;}
getans(l);
return ;
}
模拟76:集训时间已过1/3(莫名紧张
T1:构造题,找规律,发现n=a*b显然可以直接构造,n>a*b必然无解,n==a+b-1必然有解,且两个序列共用一个数,n<a+b-1必然无解
剩下的情况按照类似n==a+b-1构造即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100050
using namespace std;
int n,a,b;
int ans[N];
void work1()
{
puts("Yes");
int al=;
for(int i=n+-a;i>=;i-=a)
{
for(int j=i;j<i+a;++j)
ans[j]=++al;
}
for(int i=;i<=n;++i)
printf("%d ",ans[i]);
puts("");
return;
}
int dp[N],f[N];
inline bool judge()
{
int an1=,an2=;
for(int i=;i<=n;++i)
{
dp[i]=f[i]=;
for(int j=;j<i;++j)
{
if(ans[j]<ans[i])
{
f[i]=max(f[i],f[j]+);
}
else
{
dp[i]=max(dp[i],dp[j]+);
}
}
an1=max(an1,f[i]);
an2=max(an2,dp[i]);
}
return an1==a&&an2==b;
}
void work2()
{
for(int i=;i<=n;++i)ans[i]=i;
int ok=;
do{
if(judge()){ok=;break;}
}while(next_permutation(ans+,ans+n+));
if(!ok){puts("No");return;}
puts("Yes");
for(int i=;i<=n;++i)printf("%d ",ans[i]);
puts("");
}
void work3()
{
int al=n;
for(int i=;i<a;++i)
ans[i]=i;
for(int i=a+;i<=n;++i)
{
ans[i]=al;--al;
}
puts("Yes");
for(int i=;i<=n;++i)printf("%d ",ans[i]);
puts("");
}
void work4()
{
int al=n-(a+b-)+,i,j;
for(i=al;i<al+a-;++i)
ans[i]=i-al+; // for(int j=1;j<=n;++j)printf("%d ",ans[j]);puts("");
for(j=n;j>n-b;--j)
ans[i++]=j;
int fr=a,to=n-b,aa=a-,bb=b-,k;
// printf("aa:%d bb:%d\n",aa,bb);
i=n-(a+b-);
// printf("i:%d fr:%d to:%d\n",i,fr,to);
while()
{
// printf("i:%d\n",i);
k=max(i-bb+,);
for(int j=;j<=bb;++j)
{
ans[k]=to;
if(fr==to)break;
--to;++k;
}
i-=bb;
if(i<=)break;
// if(fr==to)break;//&&ans[k]==to
--aa;
k=max(i-aa+,);
for(int j=;j<=aa;++j)
{
ans[k]=fr;
if(fr==to)break;
++fr;++k;
}
i-=aa;
if(i<=)break;
// if(fr==to)break;
--bb;
}
puts("Yes");
for(int i=;i<=n;++i)printf("%d ",ans[i]);
puts("");
}
void work()
{
if(n<=){work2();return;}
if(1ll*a*b==n){work1();return;}
if(1ll*a*b<n){puts("No");return;}
if(a+b>n+){puts("No");return;}
if(a+b==n+){work3();return;}
work4();return;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&a,&b);
work();
}
}
T2:结论题。子任务一:暴力跑背包,二:单调队列优化多重背包,三:暴搜
结论:排序后考虑每个物品的一半和前面所有物品的sum的关系,看有没有断档即可。(摘自DeepinC的blogs)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100050
using namespace std;
int a[N];
int n,an;
inline void work4()
{
long long l=(a[]+)/,r=a[],sum=;
for(int i=;i<=n;++i)
{
if((a[i]+)/>r+)
{
sum+=r-l+;
l=(a[i]+)/;
}
r+=a[i];
}
sum+=r-l+;
cout<<sum<<endl;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i)scanf("%d",&a[i]);
sort(a+,a+n+);
work4();return ;
}
T3:考试时一直没想出来怎么搞掉限制,然后skyh大声地在纸上写AK,然后就拼命想正解,然后就想到了,然后就没时间打了,然后skyh就AK了。。。
我们发现先序遍历有很多优美的性质,然后考虑yy它,因为序列递增,把限制拍到序列上,dp[i][j]表示以i为根,子树大小为j的方案数,利用先序遍历和中序遍历的性质进行转移
对每个点记录它后面的中序限制在它前面的最大的点,和它后面的中序限制在它后面的最小的点然后就可以kx地转移了,注意子树大小为1也需要转移
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 450
const int mod=;
using namespace std;
int a[N];
int n,m,ok;
int dp[N][N],f[N][N];
void init()
{
ok=;
for(register int i=;i;--i){
f[i][]=f[i][]=;
for(register int j=;j<=;++j)
for(register int k=;k<j;++k)
(f[i][j]+=1ll*f[i+][k]*f[i+][j-k-]%mod)%=mod;
}
}
inline void work1()
{
if(!ok){init();}
cout<<f[-n+][n]<<endl;
}
struct node{int x,y;}ed[N][N];
int pre[N],las[N];
inline void work2()
{
memset(dp,,sizeof(dp));
dp[n][]=dp[n][]=dp[n+][]=;
for(int i=n-;i;--i)
{
dp[i][]=;
for(int j=;j+i-<=n;++j)
{
dp[i][j]=;
for(int k=max(pre[i]-i,);k<las[i]-i&&k<j;++k)
{
dp[i][j]+=1ll*dp[i+][k]*dp[i+k+][j-k-]%mod;
if(dp[i][j]>=mod)dp[i][j]-=mod;
}
// printf("dp[%d][%d]:%d\n",i,j,dp[i][j]);
}
}
cout<<dp[][n]<<endl;
}
int main()
{
// freopen("sample.in","r",stdin);
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
if(!m){work1();continue;}
for(int i=;i<=n;++i)las[i]=n+,pre[i]=;
for(int i=,x,y;i<=m;++i){
scanf("%d%d",&x,&y);
if(y>x)las[x]=min(las[x],y);
pre[y]=max(pre[y],x);
}
int ok=;
for(int i=;i<=n;++i)
{
if(pre[i]>=las[i]){
ok=;break;
}
}
if(ok){puts("");continue;}
work2();
}
}
ps:RP守恒,不要太飘
pps:做难题,填坑
CSPS模拟75&76的更多相关文章
- CSPS模拟 75
我身边 mikufun:矩阵树学学学 Lrefrain:矩阵题刷刷刷 Dybala:神仙定理康康康 skyh:讨论讨论讨论(most mei face) DeepinC:我过样例了! Mouding: ...
- [CSP-S模拟测试76]题解
咕咕咕 A.序列 无解情况:$n>a*b$或$n<a+b-1$ 把序列分成B段,每段内部上升,各段分界处构成下降子序列. 实现并不是太简单,要动态地考虑一下边界什么的. #include& ...
- csp-s模拟测试52-53
留坑.... 改完题再说吧. 留坑....最近考得什么鬼??模拟53T1 u(差分) 一道差分题????然而考场没有想到如何维护斜率上的差分,事后经miemeng和cyf的生(xuan)动(xue)讲 ...
- 反省——关于csp-s模拟50
本人于搜索csp-s模拟49题解时,有意识地点开了一篇关于csp-s模拟50T2的题解,并知道了题解是二维前缀和以及四维偏序. 更重要的是,那篇博客说有解法二,叫二维莫队. 于是我上网搜索二维莫队,结 ...
- csp-s模拟测试99
csp-s模拟测试99 九九归一直接爆炸. $T1$一眼板子. $T2$一眼语文题(语文的唯一一次$120+$是给模拟出来的可知我的语文能力). $T3$一眼普及题. ?? Hours Later 板 ...
- csp-s模拟测试98
csp-s模拟测试98 $T1$??不是我吹我轻松手玩20*20.$T2$装鸭好像挺可做?$T3$性质数据挺多提示很明显? $One$ $Hour$ $Later$ 这$T1$什么傻逼题真$jb$难调 ...
- csp-s模拟测试97
csp-s模拟测试97 猿型毕露.水题一眼秒,火题切不动,还是太菜了. $T1$看了一会儿感觉$woc$期望题$T1??$假的吧??. $T2$秒. $T3$什么玩意儿. 40 01:24:46 00 ...
- csp-s模拟测试96
csp-s模拟测试96 $T1$一眼慢速乘,$T2$稍证一手最优性尝试用神奇数据结构优化,无果,弃.$T3$暴力+信仰. 100 03:16:38 95 03:16:56 35 03:17:10 23 ...
- csp-s模拟测试95
csp-s模拟测试95 去世场祭. $T1$:这不裸的除法分块吗. $T2$:这不裸的数据结构优化$Dp$吗. $T3$:这不裸的我什么都不会搜索骗$30$分吗. 几分钟后. 这除法分块太劲了..(你 ...
随机推荐
- jq勾选
1.取消勾选 $("box").attr("checked", false); 2.勾选 $("kbox").attr("chec ...
- MySQL5.7主从同步配置
主从同步,将主服务器(master)上的数据复制到从服务器(slave). 应用场景 读写分离,提高查询访问性能,有效减少主数据库访问压力. 实时灾备,主数据库出现故障时,可快速切换到从数据库. 数据 ...
- Nginx server配置
项目一般都需要前后端的配置,用二级域名把它区分开:首先在nginx.conf:里面加一句话: http{ #这里面有很多其他的配置 如:gzip FastCGI等等 include vhosts/*. ...
- Jenkins 2017年用过
Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. Jenkins功能包括: 1.持续的软件版本 ...
- 联想U310 安装系统后无法识别机械硬盘处理
过程: 原30G的固态更换成250G的 mSATA固态,去掉机械硬盘,开始在固态里安装系统, 系统用PE登录,安装正版Win7 64B 专业版, 安装结束,接上机械硬盘, *PE下,可以正常识别2块硬 ...
- Java Web 深入分析(8) Servlet工作原理解析
Servlet Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态We ...
- form-create教程:自定义布局,实现一行多个组件
本文将介绍form-create如何自定义布局,实现一行多个组件 form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成器.并且支持生成任何 Vue 组 ...
- 转载一篇有关于diff的文章,方便以后复习
本文章是转载的,为了方便以后复习,特地记录一下.他人请去原地址观看!!! 文章原地址:http://www.ruanyifeng.com/blog/2012/08/how_to_read_diff.h ...
- 对SPI进行参数化结构设计
前言 为了避免每次SPI驱动重写,直接参数化,尽量一劳永逸. SPI master有啥用呢,你发现各种外围芯片的配置一般都是通过SPI配置的,只不过有3线和四线. SPI slave有啥用呢,当外部主 ...
- ubuntu16.04安装aquatone
很坑 网上的那些教程 不知道怎么搞得.... 误人子弟 首先 一台服务器 ubuntu16.04 首先aquatone github https://github.com/michenr ...