#1

Alpha planetary system

题面

我们发现集合有三个,集合内的点之间没有边,于是我们希望集合内的点权值在某种意义上相等,这样任意一条边两边的点点权肯定不同。又因为边权也是 \(1,2,3\),所以我们得到可以尝试去使得同一集合内的点的点权在 \(\bmod 3\) 意义下相等。

可以发现边权为 \(3\) 的边在 \(\bmod 3\) 意义下相当于对两边的点的点权没有贡献,相当于删掉了这条边。于是我们可以通过这样的“删边”操作,得到一棵树。得到树有什么意义呢?因为叶子节点的度数为 \(1\),所以可以直接得到叶子节点到父亲的边的权值。同理,在给一个点子树内的所有边赋权后,可以通过给该点到父亲的边赋权来调整该点在 \(\bmod 3\) 意义下权值。这样子,唯一会出问题就是根节点了。
可以发现给定一个环,若给环上的边以 \(1,2,1,2\) 的顺序加权,那么只有在环是奇环时,环的起始节点会改变 \(\bmod 3\) 意义下的权值。于是我们可以找一个奇环,令根为环上一点,最后若不符合条件,则直接按照上述方法进行调整即可。
若图中没有奇环,说明这是一个二分图。对于二分图我们调整策略,同样生成一棵树,奇数层 \(\bmod 3\) 意义下权值为 \(1\),偶数层 \(b\mod 3\) 意义下权值为 \(0\),因为没有奇环,所以这个符合条件。对于根的问题,选择一个度数大于等于 \(2\) 的点即可。如果最后不满足条件,就选两条不同的临边加 \(1\) 就行。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=1e5+10;
int n,m,belong[N],head[N],tot,col_e[N],rt;
int c[N],flag,fa[N];
struct edge{
    int u,v,nxt,id;
}e[N<<1];
void add(int u,int v,int id){
    e[++tot].v=v;
    e[tot].u=u;
    e[tot].nxt=head[u];
    e[tot].id=id;
    head[u]=tot;
}
void add_e(int u,int v,int id){
    add(u,v,id);
    add(v,u,id);
}
void dfs(int u,int color){
    int tot=0;
    c[u]=color;
    for(int i=head[u];i;i=e[i].nxt){
        tot++;
        int v=e[i].v;
        if(c[v]==color&&!flag){
            flag=i;
        }
        if(c[v]){
            continue;
        }
        fa[v]=u;
        dfs(v,3-color);
    }
    if(tot>1){
        rt=u;
    }
}
struct node{
    int u,v,w,id;
};
bool cmp(node x,node y){
    return x.u==y.u?x.id<y.id:x.u<y.u;
}
namespace odd{
    int dep[N],col_p[N],round[N],vis[N];
    void make_tree(int u,int father){
        fa[u]=father;
        dep[u]=dep[father]+1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==father){
                continue;
            }
            if(dep[v]){
                col_e[e[i].id]=3;
                continue;
            }
            make_tree(v,u);
            if(col_p[v]!=belong[v]){
                col_e[e[i].id]=((belong[v]-col_p[v]+3)%3+2)%3+1;
                col_p[u]+=col_e[e[i].id];
                col_p[u]%=3;
            }
            else{
                col_e[e[i].id]=3;
            }
        }
    }
    void change(int u,int val){
        if(vis[u]){
            return;
        }
        vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,id=e[i].id;
            if(!round[v]||round[v]!=u){
                continue;
            }
            col_e[id]=((col_e[id]+val)%3+2)%3+1;
            change(v,3-val);
        }
    }
    void solve(){
        int u=e[flag].u,v=e[flag].v;
        round[v]=u;
        while(u!=v){
            round[u]=fa[u];
            u=fa[u];
        }
        make_tree(v,0);
        if(col_p[v]!=belong[v]){
            int delta=(belong[v]-col_p[v]+3)%3*2%3;
            change(v,delta);
        }        
        for(int i=1;i<=tot;i+=2){
            write_space(e[i].u-1),write_space(e[i].v-1),write_endl(col_e[e[i].id]);
        }
    }
}
namespace even{
    int to_fa[N],dep[N],col_p[N];
    void make_tree(int u,int father){
        fa[u]=father;
        dep[u]=dep[father]+1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==father){
                continue;
            }
            if(dep[v]){
                col_e[e[i].id]=3;
                continue;
            }
            to_fa[v]=e[i].id;
            make_tree(v,u);
        }
        int col=(dep[u]%2+1)%2+1;
        if(col_p[u]!=col&&u!=1){
            col_e[to_fa[u]]=((col-col_p[u]+3)%3+2)%3+1;
            col_p[fa[u]]+=col_e[to_fa[u]];
            col_p[fa[u]]%=3;
        }
        else{
            col_e[to_fa[u]]=3;
        }
    }
    void solve(){
        make_tree(rt,0);
        if(col_p[rt]==2){
            int u=0,v=0;
            for(int i=head[rt];i;i=e[i].nxt){
                if(!u){
                    u=e[i].id;
                }
                else if(!v){
                    v=e[i].id;
                }
            }
            col_e[u]=col_e[u]%3+1;
            col_e[v]=col_e[v]%3+1;
        }
        for(int i=1;i<=tot;i+=2){
            write_space(e[i].u-1),write_space(e[i].v-1),write_endl(col_e[e[i].id]);
        }
    }
}
void solve(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        char opt=getchar();
        while(opt!='X'&&opt!='Y'&&opt!='Z'){
            opt=getchar();
        }
        belong[i]=opt-'X';
    }
    for(int i=1;i<=m;i++){
        int u,v;
        read(u),read(v);
        if(u>v){
            swap(u,v);
        }
        u++,v++;
        add_e(u,v,i);
    }
    dfs(1,1);
    if(flag){
        odd::solve();
    }
    else{
        even::solve();
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

Fibonacci Additions

题面

因为询问 \(a,b\) 数组是否相同,令 \(c_i=a_i-b_i\),两数组相同等价于 \(c\) 数组全为 \(0\)。因为让一个区间加上斐波那契数列很难维护,所以我们考虑差分维护这个信息。已知 \(Fib_i=Fib_{i-1}+Fib_{i-2}\),为了抵消须减去前面两个数,所以定义差分数组 \(d\)\(d_i=c_{i+2}-c_{i+1}-c_{i}\)。增加时在 \(l-2\) 处加 \(1\),在 \(r-1,r\) 处减去 \(Fib_{r-l},Fib_{r-l+1}\) 即可。因为 \(c_n\) 要等于 \(0\),所以 \(d_n=0\),同理推得 \(c\) 数组全为 \(0\) 等价于 \(d\) 数组全为 \(0\)。最后统计 \(d\) 数组中 \(0\) 的数量是否为 \(n\) 即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=3e5+10;
int n,q,mod,fib[N],a[N],b[N],delta[N],d[N],sum;
void update(int pos,int val){
    if(!delta[pos]){
        sum--;
    }
    delta[pos]=((delta[pos]+val)%mod+mod)%mod;
    if(!delta[pos]){
        sum++;
    }
}
void solve(){
    read(n),read(q),read(mod);
    fib[1]=fib[0]=1;
    for(int i=2;i<=n+5;i++){
        fib[i]=(fib[i-1]+fib[i-2])%mod;
    }
    for(int i=1;i<=n;i++){
        read(a[i]);
    }
    for(int i=1;i<=n;i++){
        read(b[i]);
    }
    for(int i=1;i<=n;i++){
        d[i]=((a[i]-b[i])%mod+mod)%mod;
    }
    for(int i=1;i<=n;i++){
        delta[i]=((d[i+2]-d[i+1]-d[i])%mod+mod)%mod;
        if(!delta[i]){
            sum++;
        }
        
    }
    while(q--){
        char opt=getchar();
        while(opt!='A'&&opt!='B'){
            opt=getchar();
        }
        int type;
        if(opt=='A'){
            type=1;
        }
        else{
            type=-1;
        }
        int l,r;
        read(l),read(r);
        if(l>2){
            update(l-2,type);
        }
        if(r>1){
            update(r-1,-type*fib[r-l+1]);
        }
        update(r,-type*fib[r-l]);
        if(sum==n){
            puts("YES");
        }
        else{
            puts("NO");
        }
    }

}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

Puzzle

题面

先考虑只有一行的怎么做,因为两个相交线段右边的向左,左边的向右肯定不优,所以我们肯定是原序列中的顺序一一对应。转化到两行也是一样,可以发现,连线之后,不相交优于相交,所以还是从左往右一一对应,对应的两个点能同行就同行,不能再考虑不同行对应即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=2e5+10;
int n,a[3][N],b[3][N],q[5][N],l[5],r[5];
void solve(){
    read(n);
    int s1=0,s2=0;
    for(int i=1;i<=2;i++){
        for(int j=1;j<=n;j++){
            read(a[i][j]);
            s1+=a[i][j];
        }
    }
    for(int i=1;i<=2;i++){
        for(int j=1;j<=n;j++){
            read(b[i][j]);
            s2+=b[i][j];
        }
    }
    if(s1!=s2){
        write_endl(-1);
        return;
    }
    int ans=0;
    l[1]=l[2]=l[3]=l[4]=1;
    for(int i=1;i<=n;i++){
        if(a[1][i]){
            q[1][++r[1]]=i;
        }
        if(a[2][i]){
            q[2][++r[2]]=i;
        }
        if(b[1][i]){
            q[3][++r[3]]=i;
        }
        if(b[2][i]){
            q[4][++r[4]]=i;
        }
        while(l[1]<=r[1]&&l[3]<=r[3]){
            ans+=abs(q[1][l[1]++]-q[3][l[3]++]);
        }
        while(l[2]<=r[2]&&l[4]<=r[4]){
            ans+=abs(q[2][l[2]++]-q[4][l[4]++]);
        }
        while(l[1]<=r[1]&&l[4]<=r[4]){
            ans++;
            ans+=abs(q[1][l[1]++]-q[4][l[4]++]);
        }
        while(l[2]<=r[2]&&l[3]<=r[3]){
            ans++;
            ans+=abs(q[2][l[2]++]-q[3][l[3]++]);
        }
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

Sonya and Bitwise OR

题面

先将题目弱化一下,如果没有修改怎么办。这种区间问题,一般可以想到分治解决。一次处理经过分治中心的区间。对于一个区间,分治中心会将区间分为两部分,分别为左区间的后缀和右区间的前缀。以为题目求的是或,所以我们可以得到前缀后缀或相同的段数最多有 \(\log V\) 段。带上修改,带修分治,让人最容易想到的就是线段树。

用线段树维护,每个节点存储两个 vector<pair<int,int> >,分别表示区间前缀或和后缀或的值及对应的第一个位置,合并考虑左区间的后缀和右区间的前缀,双指针做一下求合并的答案即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=1e5+10;
int n,q,x,a[N];
namespace Seg_Tree{
    struct node{
        int ans,l,r;
        vector<pii>pre,nxt;
    }tr[N<<3];
    int ls(int p){
        return p<<1;
    }
    int rs(int p){
        return p<<1|1;
    }
    void push_up(int p){
		tr[p].ans=tr[ls(p)].ans+tr[rs(p)].ans;
		for(int i=0,j=tr[ls(p)].nxt.size();i<tr[rs(p)].pre.size();++i){
            int nxt=(i<=(int)tr[rs(p)].pre.size()-2?tr[rs(p)].pre[i+1].first:tr[p].r+1);
			while(j>0&&(tr[ls(p)].nxt[j-1].second|tr[rs(p)].pre[i].second)>=x){
				--j;
            }
			if(j!=tr[ls(p)].nxt.size()){
				tr[p].ans+=1ll*(tr[ls(p)].nxt[j].first-tr[p].l+1)*(nxt-tr[rs(p)].pre[i].first);
            }
		}
		tr[p].pre=tr[ls(p)].pre;
		for(int i=0;i<tr[rs(p)].pre.size();++i){
			if(tr[p].pre.back().second!=(tr[p].pre.back().second|tr[rs(p)].pre[i].second)){
				tr[p].pre.pb(mp(tr[rs(p)].pre[i].first,tr[p].pre.back().second|tr[rs(p)].pre[i].second));
			}
		}
		tr[p].nxt=tr[rs(p)].nxt;
		for(int i=0;i<tr[ls(p)].nxt.size();++i){
			if(tr[p].nxt.back().second!=(tr[p].nxt.back().second|tr[ls(p)].nxt[i].second)){
				tr[p].nxt.pb(mp(tr[ls(p)].nxt[i].first,tr[p].nxt.back().second|tr[ls(p)].nxt[i].second));
			}
		}
	}
    void build(int p,int l,int r){
        tr[p].l=l,tr[p].r=r;
        if(l==r){
            tr[p].ans=(a[l]>=x);
            tr[p].pre.pb(mp(l,a[l]));
            tr[p].nxt.pb(mp(l,a[l]));
            return;
        }
        int mid=(l+r)>>1;
        build(ls(p),l,mid);
        build(rs(p),mid+1,r);
        push_up(p);
    }
    void update(int p,int l,int r,int pos,int val){
        if(l==r){
            tr[p].ans=(val>=x);
            tr[p].pre[0]=tr[p].nxt[0]=mp(l,val);
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid){
            update(ls(p),l,mid,pos,val);    
        }
        else{
            update(rs(p),mid+1,r,pos,val);
        }
        push_up(p);
    }
    int query(int p,int l,int r,int q_l,int q_r){
        if(l==q_l&&r==q_r){
            return tr[p].ans;
        }
        int mid=(l+r)>>1;
        if(q_r<=mid){
            return query(ls(p),l,mid,q_l,q_r);
        }
        if(q_l>mid){
            return query(rs(p),mid+1,r,q_l,q_r);
        }
        int ans=query(ls(p),l,mid,q_l,mid)+query(rs(p),mid+1,r,mid+1,q_r);
        int j=(int)tr[ls(p)].nxt.size()-1;
        while(tr[ls(p)].nxt[j].first<q_l){
            j--;
        }
        for(int i=0,R;i<tr[rs(p)].pre.size()&&tr[rs(p)].pre[i].first<=q_r;i++){
            R=(i<=(int)tr[rs(p)].pre.size()-2?tr[rs(p)].pre[i+1].first:tr[p].r+1);
            R=min(R,q_r+1);
            if((tr[ls(p)].nxt[j].second|tr[rs(p)].pre[i].second)<x){
                continue;
            }
            while(j>0&&(tr[ls(p)].nxt[j-1].second|tr[rs(p)].pre[i].second)>=x){
                j--;
            }
            ans+=1ll*(tr[ls(p)].nxt[j].first-q_l+1)*(R-tr[rs(p)].pre[i].first);
        }
        return ans;
    }
}
void solve(){
    read(n),read(q),read(x);
    for(int i=1;i<=n;i++){
        read(a[i]);
    }
    Seg_Tree::build(1,1,n);
    while(q--){
        int opt,x,y;
        read(opt);
        if(opt==1){
            read(x),read(y);
            Seg_Tree::update(1,1,n,x,y);
        }
        else{
            read(x),read(y);
            write_endl(Seg_Tree::query(1,1,n,x,y));
        }
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[HNOI2007] 神奇游乐园

题面

整理题意,求一个权值最大的哈密顿回路。求这种东西是插头 dp 的一种非常典型的题。用四进制表示一个状态,第 \(i\) 位上为 \(0\) 表示没有插头,为 \(1\) 表示存在路径的左端点,为 \(2\) 表示存在路径的右端点。

分类讨论:

  1. 左侧和上方均没有插头,此时可以选择加一个下插头和右插头,也可以不管。
  2. 左侧有插头,上方没有,此时可以继续向右走,也可以向下转。
  3. 左侧无插头,上方有,此时可以继续向下走,也可以向右转。
  4. 左侧和上方均有插头,且均为左端点或均为右端点,可以选择将两端点合并,但是在合并的时候需要注意,为了保证路径仍然闭合,我们需要将路径另一端对应的两个端点也闭合。
  5. 左侧和上方均有插头,且左边的是路径右端点,上方的是路径左端点,直接合并即可。
  6. 左侧和上方均有插头,且左边的是路径左端点,上方的是路径右端点,根据括号序列问题,只有这对括号是相互匹配的括号时,才能直接连上,可以用哈希维护。
点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=110,M=1000,mod=107,inf=1e9;
int n,m,_map[N][10],q[2][M],cnt[2],h[2][mod],v[2][mod];
int get_out(int state,int pos){
    return (state>>(pos*2))&3;
}
int get_in(int pos,int v){
    return v*(1<<(pos*2));
}
int find_pos(int tmp,int x){
    int t=x%mod;
    while(h[tmp][t]!=-1&&h[tmp][t]!=x){
        t=(t+1)%mod;
    }
    return t;
}
void ins(int tmp,int state,int val){
    int t=find_pos(tmp,state);
    if(h[tmp][t]==-1){
        h[tmp][t]=state;
        v[tmp][t]=val;
        q[tmp][++cnt[tmp]]=t;
    }
    else{
        v[tmp][t]=max(v[tmp][t],val);
    }
    return;
}
void solve(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            read(_map[i][j]);
        }
    }
    int ans=-inf;
    memset(h,-1,sizeof(h));
    int tmp=0;
    ins(tmp,0,0);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=cnt[tmp];j++){
            h[tmp][q[tmp][j]]<<=2;
        }
        for(int j=1;j<=m;j++){
            tmp^=1;
            cnt[tmp]=0;
            memset(h[tmp],-1,sizeof(h[tmp]));
            for(int k=1;k<=cnt[tmp^1];k++){
                int state=h[tmp^1][q[tmp^1][k]],val=v[tmp^1][q[tmp^1][k]],x=get_out(state,j-1),y=get_out(state,j);
                if(!x&&!y){
                    ins(tmp,state,val);
                    if(i<n&&j<m){
                        ins(tmp,state+get_in(j-1,1)+get_in(j,2),val+_map[i][j]);

                    }
                }
                else if(!x&&y){
                    if(i<n){
                        ins(tmp,state-get_in(j,y)+get_in(j-1,y),val+_map[i][j]);
                    }
                    if(j<m){
                        ins(tmp,state,val+_map[i][j]);
                    }
                }
                else if(x&&!y){
                    if(i<n){
                        ins(tmp,state,val+_map[i][j]);
                    }
                    if(j<m){
                        ins(tmp,state-get_in(j-1,x)+get_in(j,x),val+_map[i][j]);
                    }
                }
                else if(x==1&&y==1){
                    for(int l=j+1,sum=1;;l++){
                        int t=get_out(state,l);
                        if(t==1){
                            sum++;
                        }
                        else if(t==2){
                            sum--;
                        }
                        if(sum==0){
                            ins(tmp,state-get_in(j-1,x)-get_in(j,y)-get_in(l,1),val+_map[i][j]);
                            break;
                        }
                    }
                }
                else if(x==1&&y==2){
                    if(state==get_in(j-1,x)+get_in(j,y)){
                        ans=max(ans,val+_map[i][j]);
                    }
                }
                else if(x==2&&y==1){
                    ins(tmp,state-get_in(j-1,x)-get_in(j,y),val+_map[i][j]);
                }
                else{
                    for(int l=j-2,sum=1;;l--){
                        int t=get_out(state,l);
                        if(t==2){
                            sum++;
                        }
                        else if(t==1){
                            sum--;
                        }
                        if(sum==0){
                            ins(tmp,state-get_in(j-1,x)-get_in(j,y)+get_in(l,1),val+_map[i][j]);
                            break;
                        }
                    }
                }
            }
        }
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}
posted @ 2023-07-21 23:22  luo_shen  阅读(48)  评论(0)    收藏  举报