noip模拟65
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=507;
ll m,n,cnt,ans,fans;
ll fa[N*N],son[N*N];
ll id[N][N],val[N][N];
vector<ll> vec[N*N];
unordered_map<ll,ll> mp1;
struct I { ll x,y; } p[N*N];
ll getfa(ll x){ return x==fa[x] ? x : fa[x]=getfa(fa[x]) ; }
inline void change(ll x,ll opt){
if(opt){
if(!mp1[x]) ans+=son[x];
mp1[x]++;
}
else if(!(--mp1[x])) ans-=son[x],mp1.erase(x);
}
inline void solve(ll i,ll j,ll opt){ // opt==1 为增添
if(i>n or j>n) return;
if(val[i][j]) change(getfa(id[i][j]),opt);
else{
opt ? ans++ : ans--;
for(auto w : vec[id[i][j]]){
change(w,opt);
}
}
}
inline void Work_Odd(ll x){
for(int i=1;i<=n-m;i++){
for(int j=x;j<=x+m-1;j++){
solve(j,i,0),solve(j,i+m,1);
}
fans=max(ans,fans);
}
}
inline void Work_Even(ll x){
for(int i=n;i>=m+1;i--){
for(int j=x;j<=x+m-1;j++){
solve(j,i,0),solve(j,i-m,1);
}
fans=max(ans,fans);
}
}
signed main(){
File(grid);
n=read(),m=read(); char s[N]; ll x,y,res;
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=n;j++){
id[i][j]=++cnt,p[cnt].x=i,p[cnt].y=j;
val[i][j]=(s[j]=='.');
}
}
for(int i=1;i<=cnt;i++) fa[i]=i,son[i]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(val[i][j] and val[i][j+1]) fa[getfa(id[i][j+1])]=getfa(id[i][j]);
if(val[i][j] and val[i+1][j]) fa[getfa(id[i+1][j])]=getfa(id[i][j]);
}
}
for(int i=1;i<=cnt;i++){
if(!val[i]) continue;
son[getfa(i)]++,fans=max(fans,son[getfa(i)]);
}
for(int i=1;i<=cnt;i++){
x=p[i].x,y=p[i].y;
if(val[x][y]) continue;
if(val[x-1][y]) vec[i].push_back(getfa(id[x-1][y]));
if(val[x][y-1]) vec[i].push_back(getfa(id[x][y-1]));
if(val[x+1][y]) vec[i].push_back(getfa(id[x+1][y]));
if(val[x][y+1]) vec[i].push_back(getfa(id[x][y+1]));
}
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++) solve(i,j,1);
}
fans=max(fans,ans);
for(int i=1;i<=n-m+1;i++){
if(i&1){
Work_Odd(i);
for(int j=n;j>=n-m+1;j--){
solve(i,j,0),solve(i+m,j,1);
}
fans=max(fans,ans);
}
else{
Work_Even(i);
for(int j=1;j<=m;j++){
solve(i,j,0),solve(i+m,j,1);
}
fans=max(fans,ans);
}
}
printf("%lld\n",fans),exit(0);
}
B. 序列问题
签到题.
发现转移的话需要满足三个条件:\(i<j,a_i<a_j,i-a_i\le j-a_j\).
可以用 \(CDQ\) 分治 \(O(nlog^2n)\)卡常过去.
另外发现如果满足后两个条件,那么第一个条件一定满足.
于是复杂度可以直接降到 \(O(nlogn)\).
另外不用 \(BIT\),直接二分也可以做.
B_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=5e5+21;
ll m,n,cnt,ans,alls;
struct I { ll w,id,pos,res; } p[N];
struct Bit_Array{
ll res; ll c[N<<2];
inline void update(ll x,ll w){
for(;x<=alls;x+=lbt(x)) c[x]=max(c[x],w);
}
inline void del(ll x){
assert(x);
for(;x<=alls;x+=lbt(x)) c[x]=0;
}
inline ll query(ll x){
res=0; for(;x>0;x&=(x-1)) res=max(res,c[x]); return res;
}
} bit;
inline bool cmp1(I i,I j){
if(i.w!=j.w) return i.w<j.w;
if(i.pos!=j.pos) return i.pos<j.pos;
return i.id<j.id;
}
inline bool cmp2(I i,I j){ return i.id<j.id; }
void cdq(ll l,ll r){
if(l>r) return ;
if(l==r) return p[l].res=max(p[l].res,1ll),void();
ll mid=(l+r)>>1; cdq(l,mid);
sort(p+l,p+mid+1,cmp1),sort(p+mid+1,p+r+1,cmp1);
ll p1=l,p2=mid+1,res;
while(p1<=mid and p2<=r){
if(p[p1].w>=p[p2].w){
res=bit.query(p[p2].pos),p[p2].res=max(p[p2].res,res+1),p2++;
}
else{
bit.update(p[p1].pos,p[p1].res),p1++;
}
}
while(p2<=r){
res=bit.query(p[p2].pos),p[p2].res=max(p[p2].res,res+1),p2++;
}
for(int i=l;i<p1;i++) bit.del(p[i].pos);
sort(p+mid+1,p+r+1,cmp2);
cdq(mid+1,r);
}
signed main(){
File(sequence);
n=read(); ll w;
for(ll i=1;i<=n;i++){
if((w=read())>i) continue;
p[++cnt].w=w,p[cnt].id=i,p[cnt].pos=i-w+1;
}
alls=n,n=cnt,cdq(1,n);
for(int i=1;i<=n;i++) ans=max(ans,p[i].res);
printf("%lld\n",ans),exit(0);
}