CSP-S模拟17
下发文件
虽然英文题面网上都有,但是除 T3 外请不要转载这些题目的题面. 毕竟翻译是有知识产权的
A. 最大匹配
题面
题目描述
输入格式
输出格式
样例
数据范围与提示
设 ,那么 i 和 j 组合可以产生的最大贡献为 .
那么我们只需要保证 | ci - cj | 尽可能大.
所以这道题就转化成了找到 ci 最大的与 ci 最小的并将它们配对. 那么就只需要按照 ci 排序,最后前一半减小的那个值、后一半加大的那个值即可.
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define rg register
#define rll rg ll
#define maxn 200001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rll f=0,x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10|'0'); }
struct node
{
ld c; ll id;
inline friend bool operator<(rg node a,rg node b) { return a.c<b.c; }
}c[maxn];
ll n,ans,ansk;
ll a[maxn],b[maxn];
int main()
{
n=read();for(rll i=1;i<=n<<1;i++) a[i]=read(),b[i]=read(),c[i]=(node){((ld)a[i]+b[i])/2,i};
sort(c+1,c+(n<<1)+1);
for(rll i=n+1;i<=n<<1;i++) ans+=max(a[c[i].id],b[c[i].id]);
for(rll i=1;i<=n;i++) ans-=min(a[c[i].id],b[c[i].id]);
write(ans);
return 0;
}
B. 挑战ABC
题面
题目描述
输入格式
输出格式
样例
数据范围与提示
很显然,答案一定不会多于 2.
为什么?因为显然 因为最优方案一定是把整个连续的区间全部改成一个字母.
那么分别考虑 0、1 和 2 的情况.
-
0:
判断一下如果不需要操作直接输出.
虽然数据里没有 0 的点
if(cnt[1][(n<<1)+n]==cnt[2][(n<<1)+n]&&cnt[2][(n<<1)+n]==cnt[3][(n<<1)+n]) { putchar('0');putn; return 0; }
-
1:
用一个双指针,枚举左端点 l,然后找到第一个位置 r 使得区间 [l,r] 至少已有多余数量的 B 和 C(假设当前枚举的是 A). 如果这个位置正好满足相等,直接覆盖即可.
inline void chk(rll x)
{
rll y=x%3+1,z=(x+1)%3+1;
for(rll l=1,r=1;l<=(n<<1)+n;l++)
{
r=max(l,r); while(r<=(n<<1)+n&&(cnt[y][r]-cnt[y][l-1]<cnt[y][(n<<1)+n]-n||cnt[z][r]-cnt[z][l-1]<cnt[z][(n<<1)+n]-n)) r++;
if(cnt[y][r]-cnt[y][l-1]==cnt[y][(n<<1)+n]-n&&cnt[z][r]-cnt[z][l-1]==cnt[z][(n<<1)+n]-n) { putchar('1');putn; write(l);put_;write(r);put_;putchar(x|'@'); fl=1; return; }
}
}
main()
{
chk(1);if(fl) return 0;chk(2);if(fl) return 0;chk(3);if(fl) return 0;
}
-
2:
找到最小的 r,使得 [1,r] 中出现次数最多的字符出现 n 次. 仍然假设当前枚举的是 A,那么剩余需要的 B 的数量就是 n - cntB [1 ~ r]. 所以把这一段区间的变为 B,后面的变为 C.
inline void chk2(rll x)
{
rll y=x%3+1,z=(x+1)%3+1;putchar('2');putn;
write(pos+1);put_;write(pos+n-cnt[y][pos]);put_;putchar(y|'@');putn;
write(pos+n-cnt[y][pos]+1);put_;write((n<<1)+n);put_;putchar(z|'@');putn;
}
main()
{
chk2(s[pos]^'@');
}
异或 “@” 是卡常的,其实就是 1 变 A,2 变 B,3 变 C.
C. 三级跳
如果存在 p 满足 i<p<j 且 a[p]>max(a[i],a[j]),那么最优的方案一定是选择 i 和 p.
用一个单调栈找出这些 p.
询问时按照 l 从大到小排序,需要插入有用的数对,那么设 n 个标记,每一次对区间内标记取 max 或者查询 a[i] 与标记之和的最大值. 用一个线段树维护最大值即可.
点击查看代码
#include<bits/stdc++.h>
#define ll int
#define rg register
#define rll rg ll
#define maxn 500001
#define pll pair<ll,ll>
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rll f=0,x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10|'0'); }
struct node { ll v,mx,tag; }t[maxn<<2];
ll n,m,a[maxn],ans[maxn];
stack<ll> s;
vector<ll> g[maxn];vector<pll> q[maxn];
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define pushup(rt) t[rt].v=max(t[ls(rt)].v,t[rs(rt)].v),t[rt].mx=max(t[ls(rt)].mx,t[rs(rt)].mx)
inline void pushdown(rll rt)
{
if(t[rt].tag)
t[ls(rt)].tag=max(t[ls(rt)].tag,t[rt].tag),t[ls(rt)].mx=max(t[ls(rt)].mx,t[ls(rt)].v+t[rt].tag),
t[rs(rt)].tag=max(t[rs(rt)].tag,t[rt].tag),t[rs(rt)].mx=max(t[rs(rt)].mx,t[rs(rt)].v+t[rt].tag),
t[rt].tag=0;
}
inline void build(rll rt,rll l,rll r)
{
if(l==r) { t[rt].v=a[l]; return; } rll mid=(l+r)>>1;
build(ls(rt),l,mid);build(rs(rt),mid+1,r);pushup(rt);
}
inline void upd(rll rt,rll l,rll r,rll x,rll y,rll v)
{
if(x>r||y<l) return;
if(x<=l&&r<=y) { t[rt].tag=max(t[rt].tag,v); t[rt].mx=max(t[rt].mx,t[rt].v+v); return; } pushdown(rt);rll mid=(l+r)>>1;
if(x<=mid) upd(ls(rt),l,mid,x,y,v); if(y>mid) upd(rs(rt),mid+1,r,x,y,v); pushup(rt);
}
inline ll query(rll rt,rll l,rll r,rll x,rll y)
{
if(x>r||y<l) return 0;
if(x<=l&&r<=y) return t[rt].mx; /*cout<<rt<<endl;*/ pushdown(rt);rll mid=(l+r)>>1,ans=0;
if(x<=mid) ans=query(ls(rt),l,mid,x,y); if(y>mid) ans=max(ans,query(rs(rt),mid+1,r,x,y)); return ans;
}
int main()
{
n=read();for(rll i=1;i<=n;i++) a[i]=read();m=read();for(rll i=1,l,r;i<=m;i++) l=read(),q[l].push_back((pll) { r=read(),i });
build(1,1,n); for(rll i=1;i<=n;i++) { while((!s.empty())&&a[s.top()]<a[i]) g[s.top()].push_back(i),s.pop(); if(!s.empty()) g[s.top()].push_back(i); s.push(i); }
for(rll i=n;i;i--)
{
for(rll j=0;j<g[i].size();j++) upd(1,1,n,(g[i][j]<<1)-i,n,a[i]+a[g[i][j]]);
for(rll j=0;j<q[i].size();j++) ans[q[i][j].second]=query(1,1,n,i,q[i][j].first);
}
for(rll i=1;i<=m;i++) write(ans[i]),putn;
return 0;
}
D. 经典线性基
题面
题目描述
输入格式
输出格式
样例
数据范围与提示
贺的.
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define ld long double
#define rll rg ll
#define maxn 1000001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rll f=0,x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10|'0'); }
ll t,l,r,lg;
bool notp[maxn],ntp[maxn];
// lbase
ll s[65],num;
inline void ins(rll x)
{
for(rll i=lg;i+1;i--) if(x&(1ll<<i)) { if(s[i]) x^=s[i]; else { s[i]=x; num++; break; } }
}
inline void shai()
{
notp[1]=1;
for(rll i=2;i<maxn;i++) { if(notp[i]) continue; for(rll j=2;i*j<maxn;j++) notp[i*j]=1; }
}
inline void shai(rll l,rll r)
{
memset(ntp,0,sizeof(ntp)); rll t=ceil(sqrt(r));
for(rll i=1,tl,tr;i<maxn;i++) if(!notp[i])
{
if(i>t) break;tl=ceil((ld)l/i),tr=r/i;for(rll j=max(tl,(ll)2);j<=tr;j++) ntp[i*j-l]=1;
}
for(rll i=0;i<=r-l;i++) if(!ntp[i]) ins(l+i);
}
int main()
{
shai();t=read();while(t--)
{
memset(s,0,sizeof(s));num=0;l=read();lg=log2(r=read()+1)+1;
for(rll i=0;i<=lg+1;i++) if((l&(1ll<<i))&&l+(1ll<<i)<=r)
{
if(i<=16) shai(l,l+(1ll<<i)-1); else for(rll j=1;j<=i;j++) ins(1ll<<j); l+=1ll<<i;
}
for(rll i=lg+1;i+1;i--) if(l+(1ll<<i)<=r)
{
if(i<=16) shai(l,l+(1ll<<i)-1); else for(rll j=1;j<=i;j++) ins(1ll<<j); l+=1ll<<i;
}
write(1ll<<num);putn;
}
return 0;
}
--END--
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/p/16760221.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!