ACM-ICPC 2018 徐州赛区网络预赛

I题 签到 注意只有0的时候答案为1

#include <bits/stdc++.h>
using namespace std;
#define FORP(i,a,b) for(int i=a;i<=b;i++)
void solve(){
    int n;
    char ch;
    cin>>n>>ch;
    string s;cin>>s;
    s='#'+s;
    FORP(i,1,n){
    int data=abs(s[i]-ch);
    if(data==0){
        continue;
    }
    else{
        if(data<10){
        printf("%d\n",(n-i)*2+1);
        return;
        }
        else{
        printf("%d\n",(n-i)*2+2);
                return ;
        }
    }
    }
    printf("1\n");
}
int main(){
    int T;
    cin>>T;
    while(T--){
    solve();
    }
    return 0;
}

顺着思路模拟一遍,每次都是在之前那个map上更新答案
用两个map就可以了

#include <bits/stdc++.h>
using namespace std;
#define FORP(i,a,b) for(int i=a;i<=b;++i)
typedef pair<int,int> Pair;
#define mp(a,b) make_pair(a,b)
map<Pair,int>mymap[3];
void solve(){
    int n;cin>>n;
    int ans=0;
    mymap[0].clear();
    mymap[1].clear();
    FORP(i,1,n){
        int k;cin>>k;
        FORP(j,1,k){
            int x,y;
            cin>>x>>y;
            int temp=mymap[i%2][mp(x,y)]=mymap[!(i%2)][mp(x,y)]+1;
            ans=max(ans,temp);
        }
        mymap[!(i%2)].clear();
    }
    cout<<ans<<endl;
}
int main(){ 
    int T;cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

H.
先正着思考 好像不太好更新
根据正难则反的原则
倒着推一遍
单独考虑x和y的长度
It’s guaranteed that a wave will not cover the other completely.
你会发现答案的更新
ans+=(nowx-小于他的最大值)
这里有点小trick 可以lower_bound找到大于等于nowx的第一个位置,然后往前移动1次,即迭代器–

#include <bits/stdc++.h>
using namespace std;
#define FORP(i,a,b) for(int i=a;i<=b;++i)
#define REP(i,a,b) for(int i=a;i>=b;--i)
typedef pair<int,int> Pair;
#define ll long long
#define mp(a,b) make_pair(a,b)
struct node{
    ll x,y;
}p[100100];
set<ll> s;
int main(){ 
    int n;
    while(cin>>n){
        FORP(i,1,n){
            cin>>p[i].x>>p[i].y;
        }
        ll ans=0;
        s.clear();
        s.insert(0);
        REP(i,n,1){
            set<ll>::iterator It=s.lower_bound(p[i].y);
            It--;
            ans+=p[i].y-(*It);
            s.insert(p[i].y);
        }
        s.clear();
        s.insert(0);
        REP(i,n,1){
            set<ll>::iterator It=s.lower_bound(p[i].x);
            It--;
            ans+=p[i].x-(*It);
            s.insert(p[i].x);
        }
        cout<<ans<<endl;
    }
    return 0;
}

Ryuji doesn’t want to study
线段树or树状数组维护一下区间皆可

#include <bits/stdc++.h>
using namespace std;
#define FORP(i,a,b) for(int i=a;i<=b;++i)
#define lowbit(i) (i&(-i))
#define ll long long
ll n,q;
ll a[102000];
ll tree1[102000];
ll tree2[102000];
ll getsum(ll *array,ll x){
    ll sum=0;
    for(ll i=x;i;i-=lowbit(i)){
        sum+=array[i];
    }
    return sum;
}
void update(ll *array,ll x,ll val){
    for(ll i=x;i<=n;i+=lowbit(i)){
        array[i]+=val;
    }
}
int main(){
    while(cin>>n>>q){
        FORP(i,1,n){
            cin>>a[i];
            update(tree1,i,a[i]);
            update(tree2,i,a[i]*(n-i+1));
        }
        FORP(i,1,q){
            int aa,l,r;
            cin>>aa>>l>>r;
            if(aa==1){
                printf("%lld\n",getsum(tree2,r)-getsum(tree2,l-1)-(n-r)*(getsum(tree1,r)-getsum(tree1,l-1)));
            }
            else{
                update(tree1,l,r-a[l]);
                update(tree2,l,(n-l+1)*(r-a[l]));
                a[l]=r;
            }
        }
    }
    return 0;
}

K Morgana Net
题目有点长没啥人做
仔细读就发现是个矩阵乘法,然后t很大不得不快速幂搞一下 t这么大=快速幂 这个思想要有
然后想转移???
发现那个函数暗示着什么
根据那个函数写转移就好了。。。
坑点:常数比较恶心 队友带我卡了一下常数
见Mul函数。。
特性:01矩阵 0比较多的时候

#include <bits/stdc++.h>
using namespace std;
#define FORP(i,a,b) for(int i=a;i<=b;++i)
#define REP(i,a,b) for(int i=a;i>=b;--i)
typedef pair<int,int> Pair;
#define ll long long
#define mp(a,b) make_pair(a,b)
struct Matrix
{
    ll m[65][65];
    ll x,y;
}a,b,e,ans,tran;
int N,M,t;
int nf;
bool zero(ll p,ll q){
    return p<=0||q<=0||p>N||q>N;
}
Matrix Mul(Matrix A,Matrix B){
    Matrix ans;
    memset(ans.m,0,sizeof(ans.m));
    ans.x=A.x;
    ans.y=B.y;
    FORP(i,1,A.x){
        FORP(k,1,A.y){
            if(!A.m[i][k])continue;
            FORP(j,1,B.y){
                ans.m[i][j]=ans.m[i][j]^(A.m[i][k]&B.m[k][j]);
            }
        }
    }
    return ans;
}
Matrix Matrix_ppow(Matrix A,ll n){
    Matrix ret=e;
    while(n){
        if(n&1) ret=Mul(ret,A);
        A=Mul(A,A);
        n>>=1;
    }
    return ret;
}
int calnzero(){
    int cnt=0;
    FORP(i,1,nf){
        if(ans.m[1][i]==1) cnt++;
    }
    return cnt;
}
int getpos(int n,int i,int j){
    return (i-1)*n+j;
}
void init(){
    e.x=e.y=nf;
    FORP(i,1,nf){//初始化单位矩阵
        e.m[i][i]=1;
    }
}
int main(){ 
    int T;
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>T;
    while(T--){
        cin>>N>>M>>t;
        nf=N*N;
        init();     
        int m=M>>1;
        //根据同余定理 可以先处理成0 1 矩阵
        ans.x=1;
        ans.y=nf;
        FORP(i,1,N){
            FORP(j,1,N){
                int data;cin>>data;
                ans.m[1][getpos(N,i,j)]=data&1;//%2->&1
            }
        }
        b.x=b.y=M;
        FORP(i,1,M){
            FORP(j,1,M){
                int data;cin>>data;
                b.m[i][j]=data&1;
            }
        }
        memset(tran.m,0,sizeof(tran.m));
        tran.x=tran.y=nf;
        //转移矩阵
        FORP(i,1,N){
            FORP(j,1,N){
                FORP(p,i-m,i+m){
                    FORP(q,j-m,j+m){
                        if(zero(p,q)) continue;
                        tran.m[getpos(N,p,q)][getpos(N,i,j)]=b.m[p-i+m+1][q-j+m+1]&1;
                    }
                }
            }
        }
        Matrix temp=Matrix_ppow(tran,t);
        ans=Mul(ans,temp);
        cout<<calnzero()<<endl;
    }
    return 0;
}

J题 最大生成树+倍增找LCA
解法1

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define FORP(i,a,b) for(int i=a;i<=b;++i)
#define mp(a,b) make_pair(a,b)
#define db(a) (cout<<"->"<<a<<endl)
#define ll long long
const int MAXN = 252005;
typedef pair<ll, ll> Pair;
vector<Pair> G[MAXN];
vector<ll> R[MAXN];
vector<node> E;
ll dist[MAXN],fa[MAXN];
ll p[MAXN][20];
ll lg[MAXN];
ll n,m;
struct node
{
    ll from,to;
    ll w;   
    node(ll _from,ll _to,ll _w):from(_from),to(_to),w(_w){}
    friend bool operator<(node a,node b){
        return a.w>b.w;
    }
};
inline void add(ll x,ll y,ll t){
    G[x].pb(mp(y,t));
    E.pb(node(x,y,t));
}
ll getPos(ll i,ll j){
    return (i-1)*m+j;
}
void init(){
    FORP(i,0,n*m){
        fa[i]=i;
    }
    memset(dist,0,sizeof(dist));
    E.clear();
    FORP(i,1,n*m){
        G[i].clear();
        R[i].clear();
    }
}
ll find(ll x){
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
ll kruskal(){
    ll len=n*m-1;
    ll sum=0;
    FORP(i,0,(ll)E.size()-1){
        ll u=E[i].from;
        ll v=E[i].to;
        ll cost=E[i].w;
        ll fx=find(u);
        ll fy=find(v);
        if(fx!=fy){
            fa[fy]=fx;
            sum+=cost;
            R[u].pb(v);
            R[v].pb(u);
            if(--len==0) return 0;
        } 
    }
    return 0;
}
int dep[MAXN];
void init_lca(){
    for(int i=1;i<=MAXN;i++){
        lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    }
}
void dfs(int node,int fath){
    dep[node]=dep[fath]+1;
    p[node][0]=fath;
    for(int i=1;(1<<i)<=dep[node];i++){
        p[node][i]=p[p[node][i-1]][i-1];
    }
    for(int i=0;i<R[node].size();++i){
        int to=R[node][i];
        if(to!=fath)dfs(to,node);
    }
}
ll lca(ll x,ll y){
    if(dep[x]<dep[y]) swap(x,y);
    while(dep[x]>dep[y]){
        x=p[x][lg[dep[x]-dep[y]]-1];
    }
    if(x==y) return x;
    for(ll k=lg[dep[x]];k>=0;k--){
        if(p[x][k]!=p[y][k]){
            x=p[x][k];
            y=p[y][k];
        }
    }
    return p[x][0];
}
ll caldist(ll x,ll y){
    return dep[x]+dep[y]-2*dep[lca(x,y)];
}
int main(){
    while(~scanf("%lld%lld",&n,&m)) {
        init();
        FORP(i,1,n){
            FORP(j,1,m){
                char s,t;
                ll a,b;
                cin>>s>>a>>t>>b;
                ll u=getPos(i,j),v;
                //其实知道边的建立过程可以不用管字母是啥
                if(i<n){
                    v=getPos(i+1,j);
                    add(u,v,a);                 
                } 
                if(j<m){    
                    v=u+1;
                    add(u,v,b);
                }
            }
        }
        sort(E.begin(),E.end());
        kruskal();//最大生成树构建
        dfs(1,0);//预处理
        init_lca();
        ll q;
        cin>>q;
        FORP(i,1,q){
            ll x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            ll u=getPos(x1,y1);
            ll v=getPos(x2,y2);
            printf("%lld\n",caldist(u,v));
        }
    }
    return 0;
}

J题
最大生成树+LCA tarjan版 ->离线

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define FORP(i,a,b) for(int i=a;i<=b;++i)
#define mp(a,b) make_pair(a,b)
#define db(a) (cout<<"->"<<a<<endl)
#define ll long long
const int MAXN = 302005;
typedef pair<ll, ll> Pair;
vector<Pair> G[MAXN],que[MAXN];
vector<ll> R[MAXN];
ll dist[MAXN],fa[MAXN],ans[MAXN],vis[MAXN];
ll f[MAXN];
ll n,m;
struct node
{
    ll from,to;
    ll w;   
    node(ll _from,ll _to,ll _w):from(_from),to(_to),w(_w){}
    friend bool operator<(node a,node b){
        return a.w>b.w;
    }
};
vector<node> E;
inline void add(ll x,ll y,ll t){
    G[x].pb(mp(y,t));
    E.pb(node(x,y,t));
}
ll getPos(ll i,ll j){
    return (i-1)*m+j;
}
void init(){
    FORP(i,0,n*m){
        fa[i]=i;
        f[i]=i;
    }
    memset(dist,0,sizeof(dist));
    memset(ans,0,sizeof(ans));
    memset(vis,0,sizeof(vis));
    E.clear();
    FORP(i,1,n*m){
        G[i].clear();
        R[i].clear();
        que[i].clear();
    }
}
ll find(ll x){
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
ll kruskal(){
    ll len=n*m-1;
    ll sum=0;
    FORP(i,0,(ll)E.size()-1){
        ll u=E[i].from;
        ll v=E[i].to;
        ll cost=E[i].w;
        ll fx=find(u);
        ll fy=find(v);
        if(fx!=fy){
            fa[fy]=fx;
            sum+=cost;
            R[u].pb(v);
            R[v].pb(u);
            if(--len==0) return 0;
        } 
    }
    return 0;
}
ll find_f(ll x){
    return f[x]=(f[x]==x?x:find_f(f[x]));
}
void dfs(ll u,ll father){
    f[u]=u;
    vis[u]=1;
    FORP(i,0,(ll)R[u].size()-1){
        ll to=R[u][i];
        if(to==father) continue;
        else{
            dist[to]=dist[u]+1;
            dfs(to,u);
        }
    }
    FORP(i,0,(ll)(que[u].size())-1){
        ll to=que[u][i].first;
        if(vis[to]){
            ll p=find_f(to);
            ans[que[u][i].second]=abs(dist[to]-dist[p])+abs(dist[u]-dist[p]);
        }
    }
    f[u]=father;
}

int main() {
    while (~scanf("%lld%lld",&n,&m)) {
        init();
        FORP(i,1,n){
            FORP(j,1,m){
                char s,t;
                ll a,b;
                cin>>s>>a>>t>>b;
                ll u=getPos(i,j),v;
                //其实知道边的建立过程可以不用管字母是啥
                if(i<n){
                    v=getPos(i+1,j);
                    add(u,v,a);                 
                } 
                if(j<m){    
                    v=u+1;
                    add(u,v,b);
                }
            }
        }
        sort(E.begin(),E.end());
        kruskal();
        ll q;
        cin>>q;
        FORP(i,1,q){
            ll x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            ll u=getPos(x1,y1);
            ll v=getPos(x2,y2);
            que[u].pb(mp(v,i));
            que[v].pb(mp(u,i));
        }
        dfs(1,0);
        FORP(i,1,q){
            printf("%lld\n",ans[i]);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值