noip模拟18
A. 导弹袭击
维护凸包的模板题,卡卡精度就行了.
A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long int
#define ull unsigned ll
#define lf double
#define lbt(x) (x&(-x))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
inline ll read() {
ll res=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return cit?res:-res;
}
} using namespace BSS;
const ll N=3e5+21;
ll m,n;
ll stk[N],ans[N];
struct I { ll a,b,id; } p[N],bin[N];
vector<I> vec;
map<pair<ll,ll>,bool> vis;
inline bool cmp1(I i,I j){
if(i.a!=j.a) return i.a<j.a;
if(i.b!=j.b) return i.b<j.b;
return i.id<j.id;
}
inline bool cmp2(I i,I j){
if(i.a!=j.a) return i.a>j.a;
if(i.b!=j.b) return i.b<j.b;
return i.id<j.id;
}
inline lf slope(ll i,ll j){ return 1.0*bin[i].a*bin[j].a*(bin[i].b-bin[j].b)/(1.0*bin[i].b*bin[j].b*(bin[i].a-bin[j].a)); }
signed main(){
n=read(); ll l=1,r=0,cnt=0;
for(int i=1;i<=n;i++){
p[i].a=read(),p[i].b=read(),p[i].id=i;
}
sort(p+1,p+1+n,cmp1);
for(int i=1;i<=n;i++){
while(cnt and bin[cnt].a<=p[i].a and bin[cnt].b<=p[i].b)cnt--;
bin[++cnt]=p[i];
}
sort(bin+1,bin+1+cnt,cmp2);
for(int i=1;i<=cnt;i++){
while(l<r and slope(stk[r],stk[r-1])>slope(i,stk[r])) r--;
stk[++r]=i;
}
for(int i=1;i<=r;i++){
vis[mp(bin[stk[i]].a,bin[stk[i]].b)]=1;
}
sort(p+1,p+1+n,[](I i,I j)->bool{ return i.id<j.id; });
for(int i=1;i<=n;i++){
if(vis.find(mp(p[i].a,p[i].b))!=vis.end()) printf("%lld ",p[i].id);
}
exit(0);
}
B. 炼金术士的疑惑
一个高斯消元板子.
B_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define re register ll
#define lf double
#define mp make_pair
#define le strlen
const ll N=300;
const ll p=1e6+3;
const ll mod=1e9+7;
inline void read(ll &ss)
{
ss=0; bool cit=0; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
if(cit) ss=-ss;
}
map<string,ll> maps;
ll n,m,xs;
ll x[N];
lf a[N][N],H[N];
char s[N];
signed main()
{
// freopen("0.in","r",stdin);
// freopen("out","w",stdout);
read(n); lf ff,tmp; ll len,temp,flag; char ch;
for(re i=1;i<=n;i++)
{
ff=1;
for(;1;)
{
scanf("%lf",&tmp); scanf("%s",s);
if(!maps[s]) maps[s]=++xs;
a[i][maps[s]]=tmp*ff;
scanf("%s",s+1); if(s[1]=='=') break;
}
ff=-1;
for(;1;)
{
scanf("%lf",&tmp); scanf("%s",s);
if(!maps[s]) maps[s]=++xs;
a[i][maps[s]]=tmp*ff;
scanf("%s",s+1);
if(s[1]=='H' and s[2]=='=') break;
}
scanf("%lf",&H[i]); // 已经乘过负号 !!
}
ff=1;
for(;1;)
{
scanf("%lf",&tmp); scanf("%s",s);
if(!maps[s]) maps[s]=++xs;
a[n+1][maps[s]]=tmp*ff;
scanf("%s",s+1); if(s[1]=='=') break;
}
ff=-1;
for(;1;)
{
scanf("%lf",&tmp); scanf("%s",s);
if(!maps[s]) maps[s]=++xs;
a[n+1][maps[s]]=tmp*ff;
scanf("%s",s+1);
if(s[1]=='H' and s[2]=='=') break;
}
scanf("%s",s+1); xs++; m=xs;
for(re i=1;i<=n;i++) a[i][xs]=-H[i];
for(re i=1,j=1;i<=n,j<=m-1;i++,j++)
{
flag=i;
for(re k=i+1;k<=n;k++)
if(fabs(a[k][j])>fabs(a[flag][j]))
flag=k;
if(flag!=i)
for(re k=1;k<=m;k++)
swap(a[i][k],a[flag][k]);
if(!a[i][j]) { i--; continue; }
for(re k=i+1;k<=n+1;k++)
{
if(!a[k][j]) continue;
tmp=a[k][j]/a[i][j];
for(re h=j;h<=m;h++)
a[k][h]=a[k][h]-tmp*a[i][h];
}
}
printf("%.1lf",a[n+1][m]+1e-12);
return 0;
}
/*
2
1 C + 1 O2 = 1 CO2 H= -393.5
1 CO + 0.5 O2 = 1 CO2 H= -283.0
2 C + 1 O2 = 2 CO H= ?
-221.0
*/
C. 老司机的狂欢
首先是两个明显的想法:二分答案和LIS
第一问很简单,然后考虑如何做第二问.
第一关键为长度,第二关键为字典序,
于是我们选择在同一长度下转移字典序最小,
可以想象成把所有以 \(1\)~\(n\) 的数字结尾的最优链都接到一棵类似于Trie树的树上,
然后树状数组转移即可,另外\(st\)表优化..
C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
#define ll long long int
#define ull unsigned ll
#define re register ll
#define lf double
#define lb lower_bound
#define ub upper_bound
#define mp make_pair
#define lbt(x) (x&(-x))
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x);
#define Copy(x,y) memcpy(x,y,sizeof x);
inline ll read()
{
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
} using namespace BSS;
const ll N=1e5+21;
ll m,n,cnt,ans;
ll pt[N],lsh[N];
ll fa[N][25],st[N][25];
struct I { ll x,a,id; } p[N];
struct Bit{
ll res; ll c[N<<3];
inline void update(ll x,ll w){
while(x<=cnt) c[x]=max(c[x],w),x+=lbt(x);
}
inline ll query(ll x){
res=0;
while(x>0) res=max(res,c[x]),x-=lbt(x);
return res;
}
inline void clr(){
res=cnt<<1;
for(re i=1;i<=res;++i) c[i]=0;
}
}bit;
inline bool comp(I i,I j){ return i.x<j.x; }
inline void check(ll t){
bit.clr(),cnt=0; ll tmp,temp;
for(re i=1;i<=n;++i)
lsh[++cnt]=(p[i].x<<1)+p[i].a*t*t;
sort(lsh+1,lsh+1+cnt),cnt=unique(lsh+1,lsh+1+cnt)-lsh-1;
for(re i=1;i<=n;++i){
tmp=lb(lsh+1,lsh+1+cnt,(p[i].x<<1)+p[i].a*t*t)-lsh;
temp=bit.query(tmp-1)+1,bit.update(tmp,temp);
}
}
inline void ins(ll x,ll dad){
fa[x][0]=st[x][0]=dad;
for(re i=1;i<=20;++i){
fa[x][i]=fa[fa[x][i-1]][i-1],
st[x][i]=min(st[x][i-1],st[fa[x][i-1]][i-1]);
}
}
inline bool Check(pair<ll,ll> x,pair<ll,ll> y){
if(x.first!=y.first) return x.first<y.first;
ll ansx=x.second,idx=x.second,ansy=y.second,idy=y.second;
for(re i=20;i>=0;i--){
if(fa[idx][i]!=fa[idy][i]){
ansx=min(ansx,st[idx][i]),ansy=min(ansy,st[idy][i]),
idx=fa[idx][i],idy=fa[idy][i];
}
}
return ansx>ansy;
}
struct Bit_array{
pair<ll,ll> c[N<<3]; pair<ll,ll> res;
void update(ll x,pair<ll,ll> w){
while(x<=cnt){
if(Check(c[x],w)) c[x]=w;
x+=lbt(x);
}
}
pair<ll,ll> query(ll x){
res=mp(0,0);
while(x>0){
if(Check(res,c[x])) res=c[x];
x-=lbt(x);
}
// cout<<res.first<<" "<<res.second<<"\n";
return res;
}
}biy;
signed main(){
n=read(),m=read(); ll tmp; pair<ll,ll> temp;
for(re i=1;i<=n;i++) p[i].x=read(),p[i].a=read(),p[i].id=i;
sort(p+1,p+1+n,comp);
ll le=0,ri=86400,mid; ans=0;
while(le<=ri){
mid=(le+ri)>>1,check(mid);
if(bit.query(cnt)>=m) ans=mid,le=mid+1;
else ri=mid-1;
}
printf("%lld\n",ans); check(ans);
if(bit.query(cnt)>m) puts("-1"),exit(0);
for(re i=1;i<=n;i++){
tmp=lb(lsh+1,lsh+1+cnt,(p[i].x<<1)+p[i].a*ans*ans)-lsh,
temp=biy.query(tmp-1),ins(p[i].id,temp.second),
biy.update(tmp,mp(temp.first+1,p[i].id));
}
tmp=biy.query(cnt).second;
// cout<<biy.query(cnt).first<<' '<<biy.query(cnt).second<<endl;
for(re i=1;i<=m;i++) pt[i]=tmp,tmp=fa[tmp][0];
sort(pt+1,pt+1+m);
for(re i=1;i<=m;i++) printf("%lld\n",pt[i]);
exit(0);
}