A. 水题。。两个坐标重合之后看一下
B.拆数字,我们知道最大的肯定是一个,第二个我们可以从大到小遍历,找到一个不会被最大值整除的或者连续出现两次的
因为只看最大和次打 可以被 hack 掉
参照 10 5 2 2 1
C. 题意很墨迹,有三个灯, r g b 我们要求 r 与 r 之间 , g 与 g 之间 以及 b 与 b 之间距离必须被3整除,
给你一个只含 rgb 的字符串,在最小修改次数的情况下,修改使得这个字符串符合条件
我们自己推一下发现,只能是 RGBRGBRGB..... 或者 GRBGRBGRB....等6种情况,之后暴力比对,选最小的一种更新
D. 和上一题背景相同,只不过要求相邻的颜色不能一样,求最小修改
那么我们发现 RRR 的话 修改中间显然最少, RRG 就把中间改成 B RRB 改成 G。。。暴力 if 判断
E1 简单版本。。很重要,会简单版本才能对困难版本有更好的优化思路
我们知道 选择减的区间,如果最小值在里边而最大值不在里边肯定是最好结果,那么如果 n = 300 那么很显然,我们完全可以暴力枚举 最大点和 最小点, 然后求出最大极差, 更新坐标就好了
E2 hard 版本,数据范围 n 在 1e5但是 m 没有变。暴力枚举肯定不成立了,还是那个思想,最小值尽可能多减去,最大值尽可能选在使用区间外部
求区间最大值,我们一下就可以想到线段树维护,之后我们仍然跑一边 N, 枚举每个 i ( i belong 1-n ) 作为最小值,那么显然,以 i 作为起点的区间和 包住 i 的区间还有以 i 为 终点的区间,我们都要用上,而对于外部的,我们尽可能不用,因为会对整个区间最大值产生影响,所以我们要看的知识最小值,最大值直接根据当前情况推出就好了,当然如果 i 是某个区间终点,我们在跑完 i 之后就要回收这个区间,因为 如果不去回收那么很显然会对整体最大值产生影响,所以回溯一下就好了。。。
附代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
inline int read()
{
register int s=0,w=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
vector<int> st[maxn],ed[maxn],anss;
#define pb(a) push_back(a)
struct que
{
int l,r;
}q[maxn];
int n,m,a[maxn];
struct node
{
int mx, add;
int l, r;
}tr[maxn<<2];
#define ls rt<<1
#define rs rt<<1|1
inline void pushdown(int rt)
{
if(tr[rt].add != 0)
{
tr[ls].add += tr[rt].add; tr[ls].mx += tr[rt].add;
tr[rs].add += tr[rt].add; tr[rs].mx += tr[rt].add;
tr[rt].add = 0;
}
}
inline void pushup(int rt){tr[rt].mx = max(tr[ls].mx, tr[rs].mx);}
inline void build(int rt, int l, int r)
{
tr[rt].l = l; tr[rt].r = r;
if(l == r)
{
tr[rt].mx = a[l];
tr[rt].add = 0;
return;
}
int mid = (l+r)>>1;
build(ls, l, mid);
build(rs, mid+1, r);
pushup(rt);
}
inline void update(int rt, int ql, int qr, int add)
{
int l = tr[rt].l, r = tr[rt].r;
if(l >= ql && r <= qr)
{
tr[rt].mx += add;
tr[rt].add += add;
return;
}
pushdown(rt);
int mid = (l+r)>>1;
if(mid >= ql) update(ls, ql, qr, add);
if(mid < qr) update(rs, ql, qr, add);
pushup(rt);
}
inline int query(int rt, int ql ,int qr)
{
int l = tr[rt].l, r = tr[rt].r;
if(l >= ql && r <= qr)
return tr[rt].mx;
int ans = -0x3f3f3f3f;
pushdown(rt);
int mid = (l+r)>>1;
if(ql <= mid) ans = max(ans, query(ls, ql, qr));
if(qr > mid) ans = max(ans, query(rs, ql, qr));
return ans;
}
int main()
{
n=read(),m=read();
int mx = -0x3f3f3f3f, mn = 0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
a[i]=read();
mx=max(mx,a[i]);
mn=min(mn,a[i]);
}
int ans = mx-mn;
build(1, 1, n);
for(int i=1;i<=m;i++)
{
q[i].l=read(),q[i].r=read();
int s = q[i].l, e = q[i].r;
st[s].pb(e); ed[e].pb(s);
}
int id = 0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<st[i].size();j++)
{
int t = st[i][j];
update(1, i, t, -1);
}
int temp = query(1, 1, n) - query(1, i, i);
if(temp > ans)
{
ans = temp; id = i;
}
for(int j=0;j<ed[i].size();j++)
{
int t = ed[i][j];
update(1, t, i, 1);
}
}
cout<<ans<<endl;
for(int i=1;i<=m;i++)
if(q[i].l <= id && q[i].r >= id)
anss.pb(i);
cout<<anss.size()<<endl;
for(int i=0;i<anss.size();i++)
cout<<anss[i]<<' ';
return 0;
}
F 题意看了个大概。。不会。。。日后在解决。