"CSP-S simulation game" 2019 first


The exam feeling very strange.
\ (T1, T2 \) are short of a small special sentence.
\ (T3 \) called priority than the violent violenceOr violenceBut I do not know why \ (WA \) wear.
When the examination also play mine ...
In fact, the dish is original sin ah ...
___

T1 little odd to take stones

topic

click here

Examination room ideas

Beginning almost own pit, the opening test \ (5min \) to code out of a terrible explosion can zero \ (01 \) backpack.
Fortunately, the result is a few minutes before you hand out a small data card himself out of himself, and then code a \ (80pts \) code.
The method is first separated data.
For \ (A, B \) two sets of data, it is clear that violence may be over, this is no problem.
For (C \) \ set of data, the definition of \ (DP [I] \) : having a number of stone \ (I \) Min selection when stones heap.
See codes shaped turn.

#include<cstdio>
#define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define dep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i)
#define cg (c=getchar())
inline int qread(){
    int x=0,f=1;char c;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return x*f;
}
template<class T>inline void qread(T& x){
    x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
#undef cg
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}

const int MAXN=200;
const int MAXK=2500;
const int INF=0x3f3f3f3f;

int n,m,k,a[MAXN+5],maxx;
int dp[MAXK+5];

inline void init(){
    qread(n,m,k);
    for(int i=1;i<=n;++i)qread(a[i]);
}

void dfs(const int i,const int x,const int w){
    if(w>k||x>m)return;
    maxx=Max(maxx,w);
    if(i>n)return;
    dfs(i+1,x+1,w+a[i]);
    dfs(i+1,x,w);
}

inline void getDp(){
    rep(i,1,k)dp[i]=INF;
    rep(i,1,n)rep(j,a[i],k)dp[j]=Min(dp[j],dp[j-a[i]]+1);
    dep(i,k,1)if(dp[i]<=m){maxx=i;break;}
}

signed main(){
    // freopen("stone.in","r",stdin);
    // freopen("stone.out","w",stdout);
    init();
    if(n<=20)dfs(1,0,0);
    else getDp();
    printf("%d\n",maxx);
    return 0;
}

Correct

Actually my exam details of the code change, in order to save on a \ (i \) of the state, \ (J \) should descending enumeration .
I do not know the mind of the examination room what, and the details are wrong ...

#include<cstdio>
#define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define dep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i)
#define cg (c=getchar())
inline int qread(){
    int x=0,f=1;char c;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return x*f;
}
template<class T>inline void qread(T& x){
    x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
#undef cg
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}

const int MAXN=200;
const int MAXK=2500;
const int INF=0x3f3f3f3f;

int n,m,k,a[MAXN+5],maxx;
int dp[MAXK+5];

inline void init(){
    qread(n,m,k);
    for(int i=1;i<=n;++i)qread(a[i]);
}

void dfs(const int i,const int x,const int w){
    if(w>k||x>m)return;
    maxx=Max(maxx,w);
    if(i>n)return;
    dfs(i+1,x+1,w+a[i]);
    dfs(i+1,x,w);
}

inline void getDp(){
    rep(i,1,k)dp[i]=INF;
    rep(i,1,n)dep(j,k,a[i])dp[j]=Min(dp[j],dp[j-a[i]]+1);
    dep(i,k,1)if(dp[i]<=m){maxx=i;break;}
}

signed main(){
    // freopen("stone.in","r",stdin);
    // freopen("stone.out","w",stdout);
    init();
    if(n<=20)dfs(1,0,0);
    else getDp();
    printf("%d\n",maxx);
    return 0;
}

T2 "CCO 2017" Professional Network

topic

click here

Examination room ideas

The so-called information contest, in fact, data-oriented programming

Look at the data range and found a good lie two points before, then you can cheat divided for these two sets of data ...

#include<cstdio>
#include<algorithm>
#define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define dep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i)
using namespace std;
#define cg (c=getchar())
inline int qread(){
    int x=0,f=1;char c;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return x*f;
}
template<class T>inline void qread(T& x){
    x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
#undef cg
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}

const int MAXN=2e5;
const int INF=0x3f3f3f3f;

int N,maxb,ans=INF;
struct node{
    int a,b;
    inline void input(){qread(a,b);if(a==0)b=0;}
    node(){}
    node(const int A,const int B):a(A),b(B){}
    bool operator<(const node t){return b==t.b?a<t.a:b<t.b;}
}p[MAXN+5];

inline void init(){
    qread(N);
    rep(i,1,N)p[i].input(),maxb=Max(maxb,p[i].b);
}

inline void dfs30(const int,const int,const int);
inline bool cmp30(const node _x,const node _y){
    return _x.a==_y.a?_x.b<_y.b:_x.a<_y.a;
}
inline void pts30(){
    sort(p+1,p+N+1,cmp30);
    dfs30(0,0,0);
}

inline void dfs30(int tot,int state,const int cost){
    if(tot==N)return (void)(ans=Min(ans,cost));
    if(cost>ans)return;

    rep(i,1,N)if(!(state&(1<<(i-1)))&&tot>=p[i].a)++tot,state|=(1<<(i-1));

    if(tot==N)return (void)(ans=Min(ans,cost));

    rep(i,1,N)if(!(state&(1<<(i-1))))
        dfs30(tot+1,state|(1<<(i-1)),cost+p[i].b);
}

inline bool cmp15(const node _x,const node _y){
    return _x.a>_y.a;
}
inline void pts15(){
    sort(p+1,p+N+1,cmp15);
    int l=1,r=N,tot=0;ans=0;
    while(l<=r){
        while(p[r].a<=tot)--r,++tot;
        if(r<l)break;
        if(p[l].a>tot)++ans;
        ++l,++tot;
    }
}

signed main(){
    // freopen("network.in","r",stdin);
    // freopen("network.out","w",stdout);
    init();
    if(maxb==1)pts15();
    else pts30();
    printf("%d\n",ans);
    return 0;
}

answer

In fact, this question with "information through an Olympiad" is not abiding by traffic rules with the same purpose. - \ (\ text JZM} {\) big brother

First of all, we have established friendly relations with everyone in the state is certainly unique.
If we follow \ (i \) before friends, we have paid \ (j \) friends.
Well, certainly not exist \ (k (k \ neq i ) \) allows us to \ (k \) before making friends already paid \ (j \) friends.
Therefore, we \ (J \) can take \ ([0, N-1 ] \) number among.
Well, we only need to pay this \ (N \) friends when they will correspond to that \ ([0, N-1 ] \) of \ (N \) number to go to.
If \ (I \) is not spent, then its corresponding value in the constant \ ([A_i, N-1 ] \) of a number of.
Greedy, we must first satisfy those (B_i \) \ large number, so we'll spend as little as possible.
In order to be able to make the interval corresponding to the number as much as possible, we need to search from \ (A_i \) to start the enumeration.
For a \ (i \)If the \ ([A_i, N-1 ] \) has not been not correspond to the number, then it must be charged for.
So this section of code to write it well

for(int i=1,loc;i<=N;++i){
    bool f=true;
    for(int j=p[i].a;j<N;++j)if(!vis[j]){
        vis[j]=true,f=false;
        break;
    }
    if(!f)ans+=p[i].b;
}

However, this is \ (O (N ^ 2) \) algorithm, it can only get up to \ (60pts \) , so we need to use disjoint-set optimization.
Time complexity close to \ (O (N) \) , I saved a counter-Ackermann function, to slow its growth.

#include<cstdio>
#include<algorithm>
#define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define dep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i)
using namespace std;
#define cg (c=getchar())
inline int qread(){
    int x=0,f=1;char c;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return x*f;
}
template<class T>inline void qread(T& x){
    x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
#undef cg
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}

const int MAXN=2e5;

int N,ans,pre[MAXN+5];bool vis[MAXN+5];
struct node{
    int a,b;
    inline void input(){qread(a,b);}
    node(){}
    node(const int A,const int B):a(A),b(B){}
    bool operator<(const node t){return b==t.b?a<t.a:b>t.b;}
}p[MAXN+5];

inline void init(){
    qread(N);
    for(int i=1;i<=N;++i)p[i].input();
    sort(p+1,p+N+1);
}

inline int findSet(const int u){
    return u==pre[u]?u:pre[u]=findSet(pre[u]);
}

inline void calc(){
    for(int i=1;i<=N;++i)pre[i]=i;
    for(int i=1,loc;i<=N;++i){
        loc=findSet(p[i].a);
        if(loc>=N)ans+=p[i].b;
        else pre[loc]=loc+1;
    }
}

signed main(){
    init();
    calc();
    printf("%d\n",ans);
    return 0;
}

T3 "ZJOI2017" segment tree

topic

click here

Examination room ideas

Exam, I only think of a time-complexity \ (O (nm) \) violence algorithmAlthough still violence, but time was lacking
But I do not have to think carefully about its correctness.
General idea is this:
in the interrogation zone \ ([l, r] \ ) when, if there is a certain period interval \ ([l ', r' ] \) and \ (U \) is not a tree with a subtree on, then the calculation section \ ([l ', r' ] \) contribution.
However, doing so there is a problem, if the interval \ ([l ', r' '] \) is included in \ ([L, R & lt] \) , and \ (r' \) and \ (r '' \) is not the same within subtrees, then my answer would make the algorithm \ (ans \) becomes larger.
Because to do so would I be looking for can spell the interval \ ([l, r] \ ) point increases, naturally, \ (ANS \) will become larger.
Codes attached

#include<cstdio>
#define rep(i,__l,__r) for(int i=__l,i##_end_=__r;i<=i##_end_;++i)
#define dep(i,__l,__r) for(int i=__l,i##_end_=__r;i>=i##_end_;--i)
#define cg (c=getchar())
inline int qread(){
    int x=0,f=1;char c;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return x*f;
}
template<class T>inline void qread(T& x){
    x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)if(c=='-')f=-1;
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
#undef cg
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}

const int MAXN=2e5;

struct node{
    int l,r,mid,d,lc,rc;
    node(){lc=rc=0;}
    node(const int L,const int R,const int M,const int D):l(L),r(R),mid(M),d(D){lc=rc=0;}
}tre[(MAXN<<1)+5];

int N,q,ncnt,ans;
int s[(MAXN<<1)+5],tail;

inline int buildtre(const int pre,const int l,const int r,const int d){
    int now=++ncnt;
    if(l==r)return tre[now]=node(l,r,0,d),now;
    tre[now]=node(l,r,qread(),d);
    tre[now].lc=buildtre(now,l,tre[now].mid,d+1);
    tre[now].rc=buildtre(now,tre[now].mid+1,r,d+1);
    return now;
}

inline void init(){
    qread(N);
    buildtre(0,1,N,1);
}

void getNode(const int i,const int l,const int r){
    if(l<=tre[i].l&&tre[i].r<=r)return (void)(s[++tail]=i);
    if(l<=tre[i].mid)getNode(tre[i].lc,l,r);
    if(r>tre[i].mid)getNode(tre[i].rc,l,r);
}

inline void calc(const int lca,const int u){
    while(tail>0)ans+=tre[s[tail--]].d+tre[u].d-2*tre[lca].d;
}

void algor(const int i,const int u,const int l,const int r){

    // printf("algor : %d %d %d %d\n",i,u,l,r);

    if(u==i){
        getNode(i,l,r);
        calc(i,i);
        return;
    }

    if(tre[i].lc<=u&&u<tre[i].rc&&r<=tre[i].mid)algor(tre[i].lc,u,l,r);
    else if(u>=tre[i].rc&&l>tre[i].mid)algor(tre[i].rc,u,l,r);
    //以上皆为同方向的子树时
    else{
        //在不同向
        //此时一定可以保证, i 即为他们的 lca
        if(u>=tre[i].rc&&l<=tre[i].mid){//当询问区间的 部分/全部 在左边, 点在右边时
            getNode(tre[i].lc,l,Min(tre[i].mid,r));
            calc(i,u);
            if(r>tre[i].mid)algor(tre[i].rc,u,tre[i].mid+1,r);
        }
        else if(tre[i].lc<=u&&u<tre[i].rc&&r>tre[i].mid){//当询问区间的 部分/全部 在右边, 点在左边时
            getNode(tre[i].rc,Max(tre[i].mid+1,l),r);
            calc(i,u);
            if(l<=tre[i].mid)algor(tre[i].lc,u,l,tre[i].mid);
        }
        /*
        else if(u==i){//当点就是当前的点的时候, 直接在其子树中寻找区间的点进行计算
            getNode(i,l,r);
            calc(i,i);
        }
        */
    }
}

inline void getQuery(){
    int q=qread(),u,l,r;
    while(q--){ans=0;
        qread(u,l,r);
        algor(1,u,l,r);
        printf("%d\n",ans);
    }
}

signed main(){
    // freopen("0.in","r",stdin);
    // freopen("tree.out","w",stdout);
    init();
    // puts("finished input!");
    getQuery();
    return 0;
}

Correct

An encoded data structure that is more difficult.
First, we asked to solve the problem of the interval.
Look at this picture below
Here Insert Picture Description
Actually, this topic is described inside the picture is.
Suppose we need to access the interval \ ([2,4] \) , how to do it?
方法一
You can see the naked eye ... although this does not seem to find \ (OJ \) up ...
but we can see that we're looking for is a node \ ((2-3) \) and \ ((4-4) \) .
方法二
Can be used like an ordinary tree line interval were to find such complexity for such a broad segment tree is probably \ (O (n) \) is.
方法三
It may be analogous to \ (\ text {zkw} \ ) segment tree mode.
We want to access the interval \ ([2,4] \) , then the left from \ ((1-1) \) to start right from the \ ((5-5) \) started to climb together.
If the left point climb, father, son found it to be a left node, then the son of the right of its parent is sure is that we are looking for the point.
If the right point climb, found that he was the right son of the parent node, then left son of its parent node is a point that we're looking for.
It is probably the result of a search Here Insert Picture Description
in which,Point circled in red pen up special for us to pay attention , while the blue underlined that we have to get to the point.
So the time complexity of doing so? Needless to say, \ (O (the n-) \) .

These methods are put aside, take a look at what we request.
It seems to give the title \ [ans = \ sum_ {v \ in S [l, r]} dis (u, v) \] Order \ (D [U] \) : Point \ (U \) depth.
We can \ (dis (u, v) \) replaced by \ (LCA \) (time complexity \ (O (logn) \) around, do not ignore) to represent, then there \ [ans = \ sum_ {v \ in S [l , r]} d [u] + d [v] -2 \ cdot d [lca (u, v)] \] Suppose that we can process the last, we find satisfying \ (V \ in S [l, r] \) points total \ (T \) a, then the equation can be further expanded: \ [ANS = T \ CDOT D [U] + \ sum_ {V \ in S [L, R & lt ]} d [v] - \ sum_ {v \ in S [l, r]} 2 \ cdot d [lca (u, v)] \] However, this formula appears to no longer be a simplification down.

Stepping back even look at us, we have analyzed two ways outThe first man ignored
If we use 方法二, we do not seem to do anything optimization, only the tree line with standard practice, the time complexity or \ (O (the n-) \) .
If we use 方法三, then we seem to be using a tree difference .
How differential law?
Record information about each point

  • \ (TLS [U] \) : from the root to \ (u \) , a total of how much is left without a son
  • \ (trs [U] \) : from the root to \ (u \) , a total of how much his son is not the result of the right
  • \ (TDLS [U] \) : from the root to \ (u \) depth of the son left a total not seen and
  • \ (TDRS [U] \) : from the root to \ (u \) depth of the son of the right altogether and have not seen

那么我们怎么求以上内容呢?
可以在建树的时候顺便处理出来。
假设我们有一个点 \(fa\),其深度为 \(d\),它的左儿子是 \(lc\),右儿子是 \(rc\)
那么,若 \(rc\) 存在,且 \(lc\) 存在,则满足
\[trs[lc]=trs[fa]+1,tdrs[lc]=tdrs[fa]+(d+1),tls[lc]=tls[fa],tdls[lc]=tdls[fa]\]而若 \(rc\) 不存在,则有
\[trs[lc]=trs[fa],tdrs[lc]=tdrs[fa],tls[lc]=tls[fa],tdls[lc]=tdls[fa]\]如果 \(lc\) 存在,且 \(rc\) 存在,则满足
\[trs[rc]=trs[fa],tdrs[rc]=tdrs[fa],tls[rc]=tls[fa]+1,tdls[rc]=tdls[fa]+(d+1)\]然后,我们就可以在建树,或者是输入建树时预处理出以上内容即可。
接着之前说的树上差分
假若我们要求区间 \([a,b]\) ,那么我们就从 \((a-1,a-1)\)\((b+1,b+1)\) 开始往上爬。
找到它们的最近公共祖先 \(lca\),那么我们要求的公式中的 \(t、\sum_{v\in S[l,r]}d[v]\) 都可以用树上差分解决。
\(t\) 满足
\[t=trs[leafu[a-1]]-trs[lca]+tls[leafu[b+1]]-tls[lca]\]\(\sum_{v\in S[l,r]}d[v]\) 满足
\[\sum_{v\in S[l,r]}d[v]=tdrs[leafu[a-1]]-tdrs[lca]+tdls[leafu[b+1]]-tdls[lca]\]似乎以上部分都是可以使用 \(O(log)\) (寻找 \(lca\))来 \(O(1)\) 地解决问题,但是 \(ans\) 还有一个部分:
\[-\sum_{v\in S[l,r]}2\cdot d[lca(u,v)]\]这个部分能否使用树上差分呢?
答案是:肯定不行。
为什么?因为 \(v\) 在改变时,\(lca(u,v)\) 也在跟着改变。
那么怎么做?
分类讨论 \(u\) 的位置,这里就和我的暴力思路有点相像。
分以下几类:
先假设以 \(leafu[a-1]、leafu[b+1],lca\) 围成的树为 \(tre\)
\(flca()\) 为寻找 \(lca\) 的算法。

  • \(u\)\(tre\) 之外时。这样又要分两类
    - 当 \(u\)\(lca\) 的祖先,那么一定满足\[\forall v\in S[l,r],flca(u,v)=u\]
    - 当 \(u\) 不是 \(lca\) 的祖先,那么一定满足\[\forall v\in S[l,r],flca(u,v)=lca(lca,u)\]
  • \(u\)\(tre\) 之内时,对于这种情况需要自行推理。。。

Another note:
you can find, if you're talking achievements, then asked if the interval \ ([1, n] \ ) sections like there will be problems, then how to solve? In fact, we can build this map (subject to a tree, for example)
Here Insert Picture Description
Code

没时间补题啊

Guess you like

Origin www.cnblogs.com/Arextre/p/12210539.html