2*n 个人,问能否排成两行,使得两行对应位置的后面的人比前面的人高
排序后,前n个人作第一排,后n个人作第二排,判断一下即可
给一个长度为n的序列,每次操作可以选择两个位置 i , j i,j i,j,要求满足 a i , a i + 1 , . . . , a j − 1 a_i,a_{i+1},...,a_{j-1} ai,ai+1,...,aj−1均不为0
这次操作会把 a i − 1 a_i-1 ai−1, a j + 1 a_j+1 aj+1,问最少多少次操作可以使得前n-1位全变成0
结论题,除去前导0,答案为所有数字之和+0的个数
给定一个长为n的字符串,然后操作c次,每次选择l-r的部分接在后面,q次询问,每次问最终得到的字符串的第x位是什么字符
发现c比较小,我们可以直接 O ( q c 2 ) O(qc^2) O(qc2)暴力向前跳,每次找到是属于哪次操作延展出来的即可
#include
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
char s[maxn];
ll l[42],r[42],sum[42];
int n,c,q;
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&c,&q);
scanf("%s",s+1);
sum[0]=n;
for(int i=1;i<=c;i++)
{
scanf("%lld%lld",&l[i],&r[i]);
sum[i]=sum[i-1]+r[i]-l[i]+1;
}
//for(int i=1;i<=c;i++) printf("%lld ",sum[i]);
//printf("\n");
while(q--)
{
ll x; scanf("%lld",&x);
int pos=c;
for(int i=1;i<=c;i++)
if(sum[i]>=x) {pos=i; break;}
while(x>n)
{
ll delta=x-sum[pos-1]-1;
x=l[pos]+delta;
for(int i=1;i<=c;i++)
if(sum[i]>=x){pos=i; break;}
}
//printf("%lld\n",x);
printf("%c\n",s[x]);
}
}
return 0;
}
给定两个01序列s和t,询问最少对s进行多少次操作可以变成t,不能输出-1
一次操作可以选择一个位置 i i i,满足 a [ i − 1 ] ! = a [ i + 1 ] a[i-1]!=a[i+1] a[i−1]!=a[i+1],然后给 a [ i ] a[i] a[i]取反
发现一次操作相当于延展/收缩一段连续的0/1
那么答案就是s和t所有连续0/1段的有端点的坐标差的绝对值之和
如果s和t的连续段不对应就是无解
#include
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int n;
char s[maxn],t[maxn];
int rps[maxn],rpt[maxn];
int vals[maxn],valt[maxn];
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int T; scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
scanf("%s",s+1); scanf("%s",t+1);
int cnts=0,cntt=0;
ll ans=0;
s[n+1]='2';
for(int i=1;i<=n;i++)
{
if(s[i+1]==s[i]) continue;
vals[++cnts]=s[i]-'0';
rps[cnts]=i;
}
t[n+1]='2';
for(int i=1;i<=n;i++)
{
if(t[i+1]==t[i]) continue;
valt[++cntt]=t[i]-'0';
rpt[cntt]=i;
}
/*for(int i=1;i<=cnts;i++) printf("%d ",rps[i]);
printf("\n");
for(int i=1;i<=cntt;i++) printf("%d ",rpt[i]);
printf("\n");*/
int flag=0;
for(int i=1;i<=min(cnts,cntt);i++)
{
if(vals[i]!=valt[i])
{
flag=1;
break;
}
ans+=abs(rps[i]-rpt[i]);
}
if(flag || cnts!=cntt) printf("-1\n");
else
printf("%lld\n",ans);
}
return 0;
}
给定n个数,每次可以删去两个相同的x,加入一个x+1,q次询问,每次修改一个值,问能通过操作得到的最大的值是多少
我们先把初始序列能进位的都进上去,然后得到了一个01序列,然后修改的时候就是模拟二进制加法
考虑给一个位置+1,相当于给当前位置开始的连续一段1变成0,下一个0变成1
同理,给一个位置-1,相当于给当前位置开始的连续一段0变成1,下一个1变成0
线段树模拟上述操作,区间修改,单点修改,线段树上二分到第一个0/1的位置
注意要多开log个位置,考试时少了一个pushdown WA了一发
#include
using namespace std;
typedef long long ll;
const int maxn=2e5+65;
int n,q,m=2e5+50;
int a[maxn],b[maxn];
struct seg
{
int val,tag;
}tr[maxn<<2];
#define lson now<<1
#define rson now<<1|1
void pushup(int now)
{
tr[now].val=tr[lson].val+tr[rson].val;
}
void build(int now,int l,int r)
{
if(l==r)
{
tr[now].val=b[l];
return;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(now);
}
void pushdown(int now,int l,int r)
{
if(!tr[now].tag) return;
int mid=l+r>>1,tag=tr[now].tag;
tr[lson].val+=(mid-l+1)*tag;
tr[rson].val+=(r-mid)*tag;
tr[lson].tag+=tag; tr[rson].tag+=tag;
tr[now].tag=0;
}
int find_0(int now,int l,int r,int L)
{
if(tr[now].val==r-l+1) return 0;
if(l==r) return l;
pushdown(now,l,r);
int mid=l+r>>1;
if(L>mid) return find_0(rson,mid+1,r,L);
int pos=find_0(lson,l,mid,L);
if(!pos) pos=find_0(rson,mid+1,r,L);
return pos;
}
int find_1(int now,int l,int r,int L)
{
if(!tr[now].val) return 0;
if(l==r) return l;
pushdown(now,l,r);
int mid=l+r>>1;
if(L>mid) return find_1(rson,mid+1,r,L);
int pos=find_1(lson,l,mid,L);
if(!pos) pos=find_1(rson,mid+1,r,L);
return pos;
}
void modify(int now,int l,int r,int L,int R,int val)
{
if(l>=L && r<=R)
{
tr[now].val+=val*(r-l+1);
tr[now].tag+=val;
return;
}
int mid=l+r>>1;
pushdown(now,l,r);
if(L<=mid) modify(lson,l,mid,L,R,val);
if(mid>1;
pushdown(now,l,r);
if(tr[rson].val) return find_pos(rson,mid+1,r);
return find_pos(lson,l,mid);
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[a[i]]++;
for(int i=1;i<=m;i++)
{
b[i+1]+=b[i]/2;
b[i]=b[i]&1;
}
build(1,1,m);
int x,y;
for(int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
del(a[x]);
add(y);
a[x]=y;
printf("%d\n",find_pos(1,1,m));
}
return 0;
}