혜성 OJ - 문제에 대한 시뮬레이션 게임 # 1 첫째날 솔루션

게임 링크 : https://www.cometoj.com/contest/74

T1

먼저, 동작은 임의의 경우에 전체 순서를 변경하지 않고, 따라서 두 시퀀스가 ​​동일하지 밖으로 직접 판사

다음에, 정의의 동작 아는 것은 어렵지 않다 : \ (\ {B_i \} \) 와 각 비 - 제로 엔트리 대응 \ (\ {A_I \} \ ) 섹션의 각 세그먼트의 개수 수행하지 교차, 이 세그먼트의 모든 것을 원래의 순서를 정확하게 함께 넣어. 우리가 현재의 순서가 덮여있다 유지 그래서 \ (\ {A_I \} \ ) 적절한 시점마다 제로를 청소하기는 \ (\ {b_i \} \ ) 다음과 때 폭력 오른쪽으로 확장

통계 답변 : 각각의 기간은 \ (\ {A_I \} \ ) 에 \ (b_i는 \) 하나의 작업을 필요로하지만 당신은 일이면 \ (A_I = b_i \) 운영 할 필요가 없습니다. 이때 유의 \ (A_I = 0 \) 판정의 효과 일 수있다 (\ 0) \ 올 고려,이 판정 \ (I \) 이 섹션하다면 범위 내에있을 수있다

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
int n,a[100100],b[100100];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

int main()
{
    //freopen("begin2.in","r",stdin);
    int T=read();
    while (T--)
    {
        n=read();
        ll sum1=0,sum2=0;
        rep(i,1,n) {a[i]=read();sum1+=a[i];}
        rep(i,1,n) {b[i]=read();sum2+=b[i];}
        if (sum1!=sum2) {puts("-1");continue;}
        //cout << sum1 << endl;
        int r=1,ok=1,ans=0;
        rep(i,1,n)
        {
            if (!b[i]) continue;
            ll sum=0;ans++;
            int l=r;
            while ((sum<b[i]) && (r<=n)) {sum+=a[r];r++;}
            if (sum!=b[i]) {ok=0;break;}
            if ((i>=l) && (i<=r-1) && (a[i]==b[i])) ans--;
            //cout << i << " "<< l << " " << r-1 << endl;
        }
        if (ok) printf("%d\n",ans);
        else puts("-1");
    }
    return 0;
}

T2

언급 된 "최단 경로"는 최소 에지 웨이트의 경로의 최대 값을 만족해야

들면 \ ((S, t) \ ) 경로의 오른쪽 가장자리에 최소의 최대 값, 우리는 MST가 알아낼 수 후 재귀

각 재귀 같은 일을한다는 것을 발견 ((S, t)를 \ \ ) 의 최단 경로는이다 \ (MST \) 의 경로

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
struct node{int to,nxt,cost;}sq[600600];
int all=0,head[300300];
int n,m,q,fa[300300][20],f[300300],dep[300300];
ll dis[300300],bin[300300];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

int find(int x)
{
    if (f[x]==x) return x;
    f[x]=find(f[x]);
    return f[x];
}

void add(int u,int v,int w)
{
    all++;sq[all].to=v;sq[all].nxt=head[u];sq[all].cost=bin[w];head[u]=all;
}

void dfs(int u,int fu)
{
    dep[u]=dep[fu]+1;fa[u][0]=fu;
    rep(i,1,19) fa[u][i]=fa[fa[u][i-1]][i-1];
    for (int i=head[u];i;i=sq[i].nxt)
    {
        int v=sq[i].to;
        if (v==fu) continue;
        dis[v]=(dis[u]+sq[i].cost)%maxd;
        dfs(v,u);
    }
}

int LCA(int u,int v)
{
    if (dep[u]<dep[v]) swap(u,v);
    int tmp=dep[u]-dep[v];
    per(i,19,0)
        if ((tmp>>i)&1) u=fa[u][i];
    if (u==v) return u;
    per(i,19,0)
        if (fa[u][i]!=fa[v][i]) 
        {
            u=fa[u][i];v=fa[v][i];
        }
    return fa[u][0];
}

int main()
{
    n=read();m=read();
    rep(i,1,n) f[i]=i;
    bin[0]=1;
    rep(i,1,m) bin[i]=bin[i-1]*2%maxd;
    rep(i,1,m)
    {
        int x=read(),y=read();
        int fx=find(x),fy=find(y);
        if (fx!=fy)
        {
            add(x,y,i);add(y,x,i);
            f[fx]=fy;
        }
    }
    dfs(1,0);
    //rep(i,1,n) cout << dep[i] << " ";cout << endl;
    int q=read();
    while (q--)
    {
        int u=read(),v=read(),w=LCA(u,v);
        ll ans=dis[u]+dis[v]-dis[w]*2;
        ans=(ans%maxd+maxd)%maxd;
        printf("%lld\n",ans);
    }
    return 0;
}

T3

먼저 결정 \ (\ {A_I \} \ ) 의 모든 사람이 공격한다고 가정 않음 기여 모두 계수 곱 순서 \ (\ FRAC {1} { 2 ^ N} \ {1} FRAC 2 ^ {N- {}}. 1 \ cdots는 \ FRAC. 1} {2} {\) 때문에 원래 시퀀스 오름차순 최적 것을

: 다음 원하는 방정식 DP에 어렵지 않다 나열 (\.. F_i = \ FRAC 1} {2} {F_ {I} -1- + \ FRAC F_ {} + {. I-A_I 1} {2} \) , 마무리 에주고 \ (F_i = \. {} {}. 4 F_. 1} + {I \ FRAC. (1) {{}}. 4 A_I을 \ 3 FRAC) , 분명히 직접 출력 할 수 있습니다.

각각 고려 \ (A_I \)\ (F_n \) 로 기록 될 수 기여 \ (f_n = \ sum_ {내가 = 1} ^ n \ FRAC {1} {4} · (\ FRAC {3} {4} ) ^ {니켈} A_I \) , 그래서 \ (A_I \) 대답에 효과가 무게 트리 라인 유지 보수 만 순위에 관하여, 유지 보수 \ (F \) 및 순위. 이후 \ (A_I \) 큰 다이나믹 한 후 처방전 (그러나 일정한 대형을) 썼다

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=1e9;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
int rt=0,n,m,q,tot=0,a[100100],siz[3903000],lson[3903000],rson[3903000];
ll seg[3900300],tag[3903000],inv34,inv43,f[100100];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

int add(int x,int y)
{
    int ans=x+y;
    if (ans>=maxd) ans-=maxd;
    return ans;
}

ll qpow(ll x,int y)
{
    ll ans=1;
    while (y)
    {
        if (y&1) ans=ans*x%maxd;
        x=x*x%maxd;y>>=1;
    }
    return ans;
}

void pushdown(int id)
{
    if (tag[id]!=1)
    {
        if (lson[id]) 
        {
            seg[lson[id]]=seg[lson[id]]*tag[id]%maxd;
            tag[lson[id]]=tag[lson[id]]*tag[id]%maxd;
        }
        if (rson[id])
        {
            seg[rson[id]]=seg[rson[id]]*tag[id]%maxd;
            tag[rson[id]]=tag[rson[id]]*tag[id]%maxd;
        }
        tag[id]=1;
    }
}

void modify(int &id,int l,int r,int pos,ll val,int v)
{
    if (!id) {id=(++tot);tag[id]=1;}
    pushdown(id);
    seg[id]=(seg[id]+val+maxd)%maxd;siz[id]+=v;
    if (l==r) return;
    int mid=(l+r)>>1;
    if (pos<=mid) modify(lson[id],l,mid,pos,val,v);
    else modify(rson[id],mid+1,r,pos,val,v);
}

void modifyr(int &id,int l,int r,int ql,int qr,ll val)
{
    if (!id) {id=(++tot);tag[id]=1;}
    if ((l>qr) || (r<ql)) return;
    pushdown(id);
    if ((l>=ql) && (r<=qr))
    {
        seg[id]=seg[id]*val%maxd;
        tag[id]=tag[id]*val%maxd;
        return;
    }
    int mid=(l+r)>>1;
    if (ql<=mid) modifyr(lson[id],l,mid,ql,qr,val);
    if (qr>mid) modifyr(rson[id],mid+1,r,ql,qr,val);
    seg[id]=(seg[lson[id]]+seg[rson[id]])%maxd;
}

int query(int id,int l,int r,int ql,int qr)
{
    if (!id) return 0;
    if ((l>qr) || (r<ql)) return 0;
    if ((l>=ql) && (r<=qr)) return siz[id];
    int mid=(l+r)>>1;int ans=0;
    if (ql<=mid) ans+=query(lson[id],l,mid,ql,qr);
    if (qr>mid) ans+=query(rson[id],mid+1,r,ql,qr);
    return ans;
}

void add(int x)
{
    int k=query(rt,0,N,x,N)+1;
    modify(rt,0,N,x,f[k]*x%maxd,1);
    if (x) modifyr(rt,0,N,0,x-1,inv34);
}

void del(int x)
{
    int k=query(rt,0,N,x,N);
    modify(rt,0,N,x,-f[k]*x%maxd,-1);
    if (x) modifyr(rt,0,N,0,x-1,inv43);
}

void init()
{
    inv34=qpow(4,maxd-2)*3%maxd;
    inv43=qpow(3,maxd-2)*4%maxd;
    f[1]=qpow(4,maxd-2);
    rep(i,2,n) f[i]=f[i-1]*inv34%maxd;
}

int main()
{
    //freopen("relation3.in","r",stdin);
    //freopen("a.out","w",stdout);
    n=read();init();
    rep(i,1,n) {a[i]=read();add(a[i]);}
    printf("%lld\n",seg[rt]);
    q=read();
    while (q--)
    {
        int pos=read(),val=read();
        del(a[pos]);a[pos]=val;add(a[pos]);
        printf("%lld\n",seg[rt]);
    }
    return 0;
}

추천

출처www.cnblogs.com/encodetalker/p/11831115.html