noip模拟40
A. 送花
不知道该怎么评价自己想到了线段树优化\(dp\)但觉得第一题不会考\(dp\)所以不再往下考虑的想法.
如果我们找到了和之前相同的值,直接减掉这个权值的贡献就可以了..
大概就是将所有状态都枚举了出来然后用线段树优化直接取最大值.
A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
#define ll long long int
#define re register int
#define ull unsigned ll
#define lf double
#define lb lower_bound
#define ub upper_bound
#define mp make_pair
#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) memset(y,x,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=2e6+51;
ll m,n,ans;
ll c[N],d[N];
pair<ll,ll> p[N];
struct I { ll sum,lazy; } tr[N<<2];
inline void spread(ll x){
if(tr[x].lazy){
tr[x<<1].sum+=tr[x].lazy,tr[x<<1|1].sum+=tr[x].lazy,
tr[x<<1].lazy+=tr[x].lazy,tr[x<<1|1].lazy+=tr[x].lazy;
tr[x].lazy=0;
}
}
inline void pushup(ll x){
tr[x].sum=max(tr[x<<1].sum,tr[x<<1|1].sum);
}
void update(ll x,ll l,ll r,ll ql,ll qr,ll w){
if(ql>qr or (!qr) ) return ;
if(l>=ql and r<=qr){
tr[x].sum+=w,tr[x].lazy+=w;
return ;
}
ll mid=(l+r)>>1; spread(x);
if(ql<=mid) update(x<<1,l,mid,ql,qr,w);
if(qr>=mid+1) update(x<<1|1,mid+1,r,ql,qr,w);
pushup(x);
}
signed main(){
n=read(); m=read();
for(re i=1;i<=n;++i) c[i]=read();
for(re i=1;i<=m;++i) d[i]=read(),p[i].first=0,p[i].second=0;
ll l,r;
for(re i=1;i<=n;++i){
l=p[c[i]].first,r=p[c[i]].second;
p[c[i]].first=r,p[c[i]].second=i;
update(1,1,n,l+1,r,-d[c[i]]),update(1,1,n,r+1,i,d[c[i]]);
ans=max(ans,tr[1].sum);
// cout<<"ans:"<<ans<<'\n';
}
printf("%lld\n",ans);
return 0;
}
B. 星空
发现最小距离一定是不为\(0\)的直接距离..
一个我又不会的巧妙转化:
题目中让我们求:
\(|\ |x_1-x_2|\ -\ |y_1-y_2|\ |\)
然后我们四十五度翻转坐标系.
于是\((x,y)\)坐标变为了\((x+y,x-y)\)..
设新的坐标为\((r,c)\).
直接距离就是\(min(\ |r_1-r_2|\ ,\ |c_1-c_2|\ )\).然后我们可以考虑将所有距离为\(0\)的点进行并查集缩点.
然后枚举所有的边,如果这条边的长度即为第一问的答案,那么乘积累加并注意去重即可.
B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
#define ll long long int
#define re register int
#define ull unsigned ll
#define lf double
#define lb lower_bound
#define ub upper_bound
#define mp make_pair
#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) memset(y,x,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+51;
ll m,n,dis,ans;
ll fa[N];
struct I { ll x,y,id; } p[N];
inline bool comp1(I i,I j){ return i.x<j.x; }
inline bool comp2(I i,I j){ return i.y<j.y; }
ll find(ll x){ return x==fa[x] ? x : (fa[x]=find(fa[x])) ; }
unordered_map<ll,ll> siz;
map<pair<ll,ll>,ll> map1;
vector<pair<ll,ll> > vec;
signed main(){
n=read(); ll x,y; dis=1e10,p[0].x=1e10,p[0].y=1e10;
for(re i=1;i<=n;++i) x=read(),y=read(),p[i].x=x+y,p[i].y=y-x,p[i].id=i;
sort(p+1,p+1+n,comp1);
for(re i=1;i<=n;++i){
if(p[i].x!=p[i-1].x) fa[p[i].id]=p[i].id;
else fa[p[i].id]=find(p[i-1].id);
}
sort(p+1,p+1+n,comp2);
for(re i=1;i<=n;++i) if(p[i].y==p[i-1].y) fa[find(p[i].id)]=find(fa[p[i-1].id]);
for(re i=1;i<=n-1;++i)
if(find(p[i].id)!=find(p[i+1].id)){
x=abs(p[i].y-p[i+1].y);
if(dis>x){
vec.clear(); dis=x;
x=min(p[i].id,p[i+1].id),y=max(p[i].id,p[i+1].id);
vec.push_back(mp(x,y));
}
else if(dis==x){
x=min(p[i].id,p[i+1].id),y=max(p[i].id,p[i+1].id);
vec.push_back(mp(x,y));
}
}
sort(p+1,p+1+n,comp1);
for(re i=1;i<=n-1;++i)
if(find(p[i].id)!=find(p[i+1].id)){
x=abs(p[i].x-p[i+1].x);
if(dis>x){
vec.clear(); dis=x;
x=min(p[i].id,p[i+1].id),y=max(p[i].id,p[i+1].id);
vec.push_back(mp(x,y));
}
else if(dis==x){
x=min(p[i].id,p[i+1].id),y=max(p[i].id,p[i+1].id);
vec.push_back(mp(x,y));
}
}
if(vec.empty()) { puts("-1"); return 0; }
sort(vec.begin(),vec.end());
ll newsize=unique(vec.begin(),vec.end())-vec.begin();
vec.resize(newsize);
for(re i=1;i<=n;++i) ++siz[find(i)];
for(auto i : vec){
x=find(i.first),y=find(i.second);
if((!map1[mp(x,y)]) and (!map1[mp(y,x)])) ans+=siz[x]*siz[y];
map1[mp(x,y)]=1,map1[mp(y,x)]=1;
}
printf("%lld\n%lld",dis,ans);
return 0;
}
C. 零一串
感谢 y_cx 大佬的讲解.
大概就是双端队列维护\(01\)相对位置即可.
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 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=5e6+21,mod=998244353;
char s[N];
ll n,m,ans,cnt;
ll a[N],c[N],pos[N],cf[N];
deque<ll> que;
inline ll ksm(ll a,ll b,ll c){
a%=c; ll res=1;
while(b){
if(b&1) res=(res*a)%c;
a=(a*a)%c,b>>=1;
}
return res%c;
}
signed main(){
m=read(),scanf("%s",s+1),n=strlen(s+1); ll tmp,res=0,pre=0;
for(re i=1;i<=n;i++){
if(s[i]=='1') a[i]=1,pos[++cnt]=i;
else a[i]=0,res+=cnt;
}
ans=(res%=mod);
for(int i=1;i<=m;i++) que.push_back(i);
for(ll i=1;i<=cnt;i++){
if(que.back()+i>m and que.size()) que.pop_back();
que.push_front(1-i);
for(re j=1;j<=pos[i]-pos[i-1]-1 and que.size();j++){
cf[que.front()+i]++,cf[min(cnt+que.front()+1,m+1)]--;
que.pop_front();
}
c[pos[i]+que.size()-m]=1;
}
for(re i=1;i<=m;i++){
pre=(pre+cf[i])%mod,res=(res+pre)%mod;
ans=ans xor (ksm(233,i,mod)*res%mod);
}
for(re i=1;i<=n;i++) cout<<c[i];
printf("\n%lld\n",ans),exit(0);
}