• 2019 CCPC-Wannafly Winter Camp Day5(Div2, onsite)


    solve 5/11

    补题:7/11

    A Cactus Draw

    Code:zz

    Thinking :zz

    题意:要在n*n的网格内画上一棵节点数为n树,使得没有边相交。

    很好想的构造题,因为网格有n*n,足够大,所以结点1放在(1,1)的位置,与结点1相连的结点依次放在(2,1),(2,2)...的位子,依此类推。

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<string>
    #include<math.h>
    #include<cmath>
    #include<time.h>
    #include<map>
    #include<set>
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<numeric>
    #include<stack>
    #include<bitset>
    #include<unordered_map>
    const int maxn = 0x3f3f3f3f;
    const double EI = 2.71828182845904523536028747135266249775724709369995957496696762772407663035354594571382178525166427;
    const double PI = 3.141592653589793238462643383279;
    using namespace std;
    struct s
    {
        int a,b;
    }z[2020],ans[2020];
    vector<int>ve[2020];
    int c[2020],hi[2020],d[2020];
    int main(void)
    {
        int n,m,i,si,j,pos,cnt;
        while(~scanf("%d %d",&n,&m))
        {
            memset(c,0,sizeof(c));
            memset(d,0,sizeof(d));
            memset(hi,0,sizeof(hi));
            for(i = 0;i <= n;i++)
            {
                ve[i].clear();
            }
            for(i = 0;i < m;i++)
            {
                scanf("%d %d",&z[i].a,&z[i].b);
                ve[z[i].a].push_back(z[i].b);
                ve[z[i].b].push_back(z[i].a);
            }
            /*for(i = 1;i <= n;i++)
            {
                printf("%d: ",i);
                for(j = 0;j < ve[i].size();j++)
                {
                    printf("%d ",ve[i][j]);
                }
                printf("
    ");
            }*/
            queue<int>q;
            q.push(1);
            cnt = 0;
            c[1] = 1;
            d[1] = 1;
            hi[1] = 1;
            while(!q.empty())
            {
                pos = q.front();
                
                q.pop();
                //c[pos] = cnt++;
                //printf("%d %d
    ",c[pos],d[pos]);
                ans[pos].a = c[pos];
                ans[pos].b = d[pos];
                si = ve[pos].size();
                //printf("pos = %d : ",pos);
                for(j = 0;j < si;j++)
                {
                    //printf("   %d ",ve[pos][j]);
                    if(!c[ve[pos][j]])
                    {
                        c[ve[pos][j]] = c[pos] + 1;
                        d[ve[pos][j]] = hi[c[ve[pos][j]]] + 1;
                        hi[c[ve[pos][j]]]++;
                        q.push(ve[pos][j]);
                    }
                }
                //printf("
    ");
            }
            for(i = 1;i <= n;i++)
            {
                printf("%d %d
    ",ans[i].a,ans[i].b);
            }
        }
        return 0;
    }
    View Code

    C Division

    Code:zz

    Thinking:zz

    k很大,有1e9,但是n只有1e5,ai只有1e9,所以最多经过1e5*log(1e9)就能使所有数字变为0。用一个优先队列来存放数字,每次取出最大的一个并/2,然后放回,等到取出的数字为0或者操作次数用尽,就退出,然后把优先队列里的值加起来就好了。

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<string>
    #include<math.h>
    #include<cmath>
    #include<time.h>
    #include<map>
    #include<set>
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<numeric>
    #include<stack>
    #include<bitset>
    #include<unordered_map>
    const int maxn = 0x3f3f3f3f;
    const double EI = 2.71828182845904523536028747135266249775724709369995957496696762772407663035354594571382178525166427;
    const double PI = 3.141592653589793238462643383279;
    using namespace std;
    long long c[100010];
    int main(void)
    {
        int n, m, i;
        long long ans, pos;
        while (~scanf("%d %d", &n, &m))
        {
            priority_queue<long long>q;
            for (i = 0; i < n; i++)
            {
                scanf("%lld", c + i);
                q.push(c[i]);
            }
            while (m > 0)
            {
                pos = q.top();
                //printf("%d
    ",pos);
                q.pop();
                if (pos == 1 || m == 0)
                {
                    break;
                }
                pos /= 2;
                q.push(pos);
                m--;
            }
            ans = 0;
            while (!q.empty())
            {
                pos = q.top();
                q.pop();
                ans += pos;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    View Code

    D Doppelblock

    搜索,待补,比赛的时候kk和pai爷提出了两个能ac的想法,但踏马的就是没写。

    补题:zz

    这是一道搜索题,可以先根据n和两个X之间的值的和枚举两个X的位置,再枚举两个X之间的数字可能的组合,可以通过预处理先把n=5,6,7时的所有和的情况全部处理出来,可以用二进制枚举达到这一点;其次,我还考虑了好多剪枝,在填上数字或者X的时候,判断行列是否有重复元素,如果填入的数字是在两个X之间的,判断能否用当前已有的两个X之间的数字来拼出相应的值,如果填入的数字是在两个X外面的,判断能否用除了这个数字以外的数字拼出相应的值,同时如果当前两个X外的值相加(1+2+...+n)-相应两个X之间的值,那么是非法。这道题补得可以说是非常难受了,好多细节出了问题,改了好久bug。

    //#pragma comment(linker, "/STACK:102400000,102400000")
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<string>
    #include<math.h>
    #include<cmath>
    #include<time.h>
    #include<map>
    #include<set>
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<numeric>
    #include<stack>
    #include<bitset>
    #include<unordered_map>
    const int maxn = 0x3f3f3f3f;
    const double EI = 2.71828182845904523536028747135266249775724709369995957496696762772407663035354594571382178525166427;
    const double PI = 3.141592653589793238462643383279;
    //#ifdef TRUETRUE
    //#define gets gets_s
    //#endif
    using namespace std;
    int n;
    int c[3][10];
    int ans[11][11];
    int ma[11] = { 6,10,15 };
    unordered_map<int, int>mp1[11][22], mp2[11], mmp;
    struct s
    {
        int nn, num[66], c[66][66];
    }z[11][22];
    inline void init(void)
    {
        int i, j, zz, sum, tmp[20], tt, l;
        for (i = 5; i <= 7; i++)
        {
            for (j = 0; j <= 15; j++)
            {
                z[i][j].nn = 0;
            }
        }
        for (i = 5; i <= 7; i++)
        {
            for (zz = 0; zz < (1 << (i - 2)); zz++)
            {
                sum = 0;
                tt = 0;
                for (j = 1; j <= i - 2; j++)
                {
                    if ((zz & (1 << (j - 1))))
                    {
                        sum += j;
                        tmp[tt++] = j;
                    }
                }
                for (j = 0; j < tt; j++)
                {
                    z[i][sum].c[z[i][sum].nn][j] = tmp[j];
                }
                z[i][sum].num[z[i][sum].nn] = tt;
                z[i][sum].nn++;
            }
        }
    
        unordered_map<int, int>mp3;
        unordered_map<int, int>mp4;
        for (i = 5; i <= 7; i++)
        {
            for (j = 0; j <= ma[i - 5]; j++)
            {
                mp3.clear();
                for (int zzz = 0; zzz < z[i][j].nn; zzz++)
                {
                    //printf("*%d %d
    ", z[i][j].num[zzz], j);
                    for (int k = 0; k < z[i][j].num[zzz]; k++)
                    {
                        if (zzz == 0)
                        {
                            mp3[z[i][j].c[zzz][k]] = 1;
                        }
                        else
                        {
                            if (mp3[z[i][j].c[zzz][k]])
                            {
                                mp4[z[i][j].c[zzz][k]] = 1;
                            }
                        }
                        //printf("%d ", z[i][j].c[zzz][k]);
                    }
                    if (zzz)
                    {
                        mp3 = mp4;
                    }
                    mp4.clear();
                    //printf("
    ");
                }
                mp1[i][j] = mp3;
    
                /*printf("- ");
                for (int rrr = 0;rrr <= 15;rrr++)
                {
                if (mp1[i][j][rrr])
                {
                printf("%d ",rrr);
                }
                }
                printf("
    ");
                printf("
    ");*/
    
            }
            //printf("************************************************
    ");
        }
    }
    
    inline bool checkx(int x, int y)
    {
        int i, sum = 0;
        int mmpt[20];
        memset(mmpt, 0, sizeof(mmpt));
        for (i = x; i >= 1; i--)
        {
            if (ans[i][y] == -1)
            {
                mmpt[17]++;
            }
            else
            {
                mmpt[ans[i][y]]++;
            }
            if (ans[i][y] == -1 && mmpt[17] >= 3 || ans[i][y] != -1 && mmpt[ans[i][y]] >= 2)
            {
                return false;
            }
            if (i <= x - 1)
            {
                if (ans[i][y] > 0)
                {
                    sum += ans[i][y];
                }
                else
                {
                    if (sum != c[1][y])
                    {
                        return false;
                    }
                    return true;
                }
            }
        }
        if (sum > ma[n - 5] - c[1][y])
        {
            return false;
        }
        return true;
    }
    inline bool checknum(int x, int y)
    {
        int i, sum = 0, tmp = 0, sum2 = 0, flag3, j;
        int mmpt[20];
        memset(mmpt, 0, sizeof(mmpt));
        for (i = x; i >= 1; i--)
        {
            if (ans[i][y] == -1)
            {
                mmpt[17]++;
            }
            else
            {
                mmpt[ans[i][y]]++;
            }
            if (ans[i][y] == -1 && mmpt[17] >= 3 || ans[i][y] != -1 && mmpt[ans[i][y]] >= 2)
            {
                return false;
            }
            if (ans[i][y] == -1)
            {
                tmp++;
            }
        }
        memset(mmpt, 0, sizeof(mmpt));
        /*for (i = 1; i <= y; i++)
        {
            if (ans[x][i] > 0)
            {
                mmpt[ans[x][i]]++;
            }
            if (ans[x][i] > 0 && mmpt[ans[x][i]] >= 2)
            {
                return false;
            }
        }*/
        if (tmp == 0)
        {
            if (mp1[n][c[1][y]][ans[x][y]] != 0)
            {
                return false;
            }
            int mmmp[20];
            memset(mmmp, 0, sizeof(mmmp));
            for (i = 1; i <= x; i++)
            {
                if (ans[i][y] > 0)
                {
                    mmmp[ans[i][y]] = 1;
                }
            }
            int flag10;
            for (i = 0; i < z[n][c[1][y]].nn; i++)
            {
                flag10 = 1;
                for (j = 0; j < z[n][c[1][y]].num[i]; j++)
                {
                    if (mmmp[z[n][c[1][y]].c[i][j]])
                    {
                        flag10 = 0;
                        break;
                    }
                }
                if (flag10)
                {
                    break;
                }
            }
            if (flag10 == 0)
            {
                return false;
            }
        }
        else if (tmp == 1)
        {
            int mmmp[20];
            memset(mmmp, 0, sizeof(mmmp));
            int biaoji[20];
            for (i = x; i >= 1; i--)
            {
                if (ans[i][y] == -1)
                {
                    break;
                }
                mmmp[ans[i][y]] = 1;
            }
            int flag10;
            for (i = 0; i < z[n][c[1][y]].nn; i++)
            {
                memset(biaoji, 0, sizeof(biaoji));
                flag10 = 1;
                for (j = 0; j < z[n][c[1][y]].num[i]; j++)
                {
                    biaoji[z[n][c[1][y]].c[i][j]] = 1;
                }
                for (j = 0; j <= 15; j++)
                {
                    if (!(mmmp[j] && biaoji[j] || !mmmp[j]))
                    {
                        flag10 = 0;
                        break;
                    }
                }
                if (flag10)
                {
                    break;
                }
            }
            if (flag10 == 0)
            {
                return false;
            }
        }
        flag3 = 1;
        for (i = x; i >= 1; i--)
        {
            if (ans[i][y] != -1)
            {
                if (flag3)
                {
                    sum += ans[i][y];
                }
            }
            else
            {
                if (tmp == 1 && sum > c[1][y])
                {
                    return false;
                }
                else if (tmp == 1)
                {
                    return true;
                }
                else if (tmp == 2)
                {
                    if (flag3)
                    {
                        flag3 = 0;
                        sum2 = sum;
                        sum = 0;
                    }
                    else
                    {
                        flag3 = 1;
                    }
                }
            }
        }
        if (sum + sum2 > ma[n - 5] - c[1][y])
        {
            return false;
        }
        return true;
    }
    
    int qq[10][20];
    int sss;
    inline void dfs(int x, bool flag, int pos)
    {
    
        /*for (int i = 1; i <= n && 1; i++)
        {
        for (int j = 1; j <= n; j++)
        {
        printf("%d ", ans[i][j]);
        }
        printf("
    ");
        }*/
    
        if (x > n)
        {
            sss = 1;
            return;
        }
        int i, j, l;
        int ss = 0;
        for (i = 1; i <= n; i++)
        {
            if (ans[x][i] == 0)
            {
                ss++;
            }
        }
        if (ss == 0 && !sss)
        {
            dfs(x + 1, false, 1);
            if (sss)
            {
                return;
            }
        }
        if (!flag)
        {
            for (l = 0; l < z[n][c[0][x]].nn && !sss; l++)
            {
                for (i = 1; i + z[n][c[0][x]].num[l] + 1 <= n && !sss; i++)
                {
                    ans[x][i] = -1;
                    ans[x][i + z[n][c[0][x]].num[l] + 1] = -1;
                    if (checkx(x, i) && checkx(x, i + z[n][c[0][x]].num[l] + 1) && !sss)
                    {
                        if (z[n][c[0][x]].num[l] == 0)
                        {
                            memset(qq[x], 0, sizeof(qq[x]));
                            dfs(x, true, 1);
                            memset(qq[x], 0, sizeof(qq[x]));
                            if (sss)
                            {
                                return;
                            }
                        }
                        else
                        {
                            sort(z[n][c[0][x]].c[l], z[n][c[0][x]].c[l] + z[n][c[0][x]].num[l]);
                            memset(qq[x], 0, sizeof(qq[x]));
                            for (int yyy = 0;yyy < z[n][c[0][x]].num[l];yyy++)
                            {
                                qq[x][z[n][c[0][x]].c[l][yyy]] = 1;
                            }
                            int ssss = 0;
                            do
                            {
                                ssss++;
                                int qw[66];
                                memcpy(qw, z[n][c[0][x]].c[l], sizeof(int) * z[n][c[0][x]].num[l]);
                                bool flag2 = true;
                                for (j = 0; j < z[n][c[0][x]].num[l]; j++)
                                {
                                    ans[x][i + j + 1] = z[n][c[0][x]].c[l][j];
                                    if (!checknum(x, i + j + 1))
                                    {
                                        flag2 = false;
                                        break;
                                    }
                                }
                                if (flag2)
                                {
                                    dfs(x, true, 1);
                                    if (sss)
                                    {
                                        return;
                                    }
                                }
                                memcpy(z[n][c[0][x]].c[l], qw, sizeof(int) * z[n][c[0][x]].num[l]);
                            } while (next_permutation(z[n][c[0][x]].c[l],
                                z[n][c[0][x]].c[l] + z[n][c[0][x]].num[l]));
                            memset(qq[x], 0, sizeof(qq[x]));
                        }
                    }
                    for (j = 1; j <= n; j++)
                    {
                        ans[x][j] = 0;
                    }
                }
            }
        }
        else
        {
    
            for (i = pos; i <= n && !sss; i++)
            {
                if (ans[x][i] == 0)
                {
                    //printf("qq = %d
    ",qq[4]);
                    for (j = 1; j <= n - 2 && !sss; j++)
                    {
                        if (qq[x][j])
                        {
                            continue;
                        }
                        ans[x][i] = j;
                        qq[x][j] = 1;
                        if (checknum(x, i))
                        {
                            dfs(x, true, i + 1);
                            qq[x][j] = 0;
                            if (sss)
                            {
                                return;
                            }
                        }
                        qq[x][j] = 0;
                        ans[x][i] = 0;
                    }
                    break;
                }
            }
        }
    }
    int main(void)
    {
        //ios::sync_with_stdio(false);
        init();
        int T, i, j;
        scanf("%d", &T);
        while (T--)
        {
            scanf("%d", &n);
            memset(ans, 0, sizeof(ans));
            for (i = 1; i <= n; i++)
            {
                scanf("%d", &c[0][i]);
            }
            for (i = 1; i <= n; i++)
            {
                scanf("%d", &c[1][i]);
            }
            sss = 0;
            dfs(1, false, 1);
            for (i = 1; i <= n; i++)
            {
                for (j = 1; j <= n; j++)
                {
                    if (ans[i][j] == -1)
                    {
                        printf("X");
                    }
                    else
                    {
                        printf("%d", ans[i][j]);
                    }
                    /*if (j != n)
                    {
                    printf(" ");
                    }*/
                }
                printf("
    ");
            }
            if (T)
            {
                printf("
    ");
            }
        }
        return 0;
    }
    View Code

    F Kropki

    Code:kk

    Thinking:pai爷  kk

    状压dp

    f[ i ] [ s ] [ j ] +=f[ i-1 ] [ s' ][ k ]

    表示第 i 个位置,状态为s(二进制),第i个位置填j的状态,然后就从题目给出的限制条件进行转移,看代码即可理解。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const ll p=1e9+7;
    ll f[18][(1<<15)+10][18];
    int n;
    char op[20];
    int main(){
        while(cin>>n){
            scanf("%s",op+1);
            CLR(f,0);
            for(int i=1;i<=n;i++)
            {
                f[1][1<<(i-1)][i]=1;
            }
            int tmp=0,tot=0; 
            for(int i=2;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    for(int s=0;s<(1<<n);s++)
                    {
                        tmp=s;//判断数字个数 合法 
                        tot=0;
                        while(tmp>0){
                            tot+=tmp%2;
                            tmp>>=1;
                        }
                        if(tot!=i)continue;
                        
                        if(( s&(1<<(j-1)) )==0)continue;//没有了 j 
                        for(int k=1;k<=n;k++)
                        {
                            if(k==j)continue;
                            if((1<<(k-1))&s==0)continue;//没有k 
                            
                            if(op[i-1]=='0'){
                                if((j/k!=2||j%k!=0) && (k/j!=2||k%j!=0) ){
                                    f[i][s][j]+=f[i-1][s^(1<<(j-1))][k]%p;
                                    f[i][s][j]%=p;
                                }
                            }else{
                                if((j/k==2&&j%k==0 )|| (k/j==2&&k%j==0)){
                                    f[i][s][j]+=f[i-1][s^(1<<(j-1))][k]%p;
                                    f[i][s][j]%=p;
                                }
                            }
                        }
                    }
                }
            }
            ll ans=0;
        //    printf("debug:%d
    ",(1<<n)-1);
            for(int j=1;j<=n;j++)
            {
                ans=(ans+f[n][(1<<n)-1][j]%p)%p;
            }
            printf("%lld
    ",ans);
        }
    }
    View Code

    H Nested Tree

    Code: kk

    Thinking :pai爷  kk

    添加边,其实就是连成了一棵树,就是!一!棵!树!没有其他的有的没的,树形dfs一下,记录一下每个节点的儿子树,父边被走过的总数量就是 son[ i ]* (n-son[ i ]) 

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+10;
    int head[maxn],tot;
    struct edge{
        int to,Next;
    }a[maxn<<2];
    ll son[maxn];
    int n,m,x,y,u,v;
    ll zo;
    ll ans=0;
    const ll p=1e9+7;
    void init(){
        CLR(son,0);
        CLR(head,-1);
        tot=0;
        ans=0;
    }
    void addv(int u,int v){
        a[++tot].to=v;
        a[tot].Next=head[u];
        head[u]=tot;
    }
    void dfs(int u,int fa){
        son[u]=1;
        for(int i=head[u];i!=-1;i=a[i].Next)
        {
            int v=a[i].to;
            if(v==fa)continue;
            dfs(v,u);
            son[u]+=son[v];
        }
        if(fa!=-1){
            ans=(ans+son[u]*(zo-son[u])%p)%p;
        }
    }
    int main(){
        while(cin>>n>>m)
        {
            init();
            zo=((ll)n*m);
            for(int i=1;i<n;i++)
            {
                scanf("%d%d",&u,&v);
                addv(u,v);
                addv(v,u);
                for(int j=2;j<=m;j++)
                {
                addv((j-1)*n+u,(j-1)*n+v);
                addv((j-1)*n+v,(j-1)*n+u);
                }
            }
            m--;
            while(m--)
            {
                scanf("%d%d%d%d",&x,&y,&u,&v);
                addv((x-1)*n+u,(y-1)*n+v);
                addv((y-1)*n+v,(x-1)*n+u);
            }
            dfs(1,-1);
            printf("%lld
    ",ans);
        }
    }
    View Code

    I Sorting

    补题:kk

    听了杜教讲的做法,好巧妙。

    对于题目中所说的两种改变区间的操作,有一个性质就是,对于所有大于x的数字,不管怎么变换,这些数字的相对位子都不变,小于等于x的数字也是这样。所以我们把大于x的数字变成1,小于等于x的数字变成0,在变化之前,先处理出每种数字的前缀和,然后用线段树来维护01序列。对于第2种操作,其实就是把 [ l , r ]的所有的0移到左边,1移到右边,这个用线段树就很好操作,第3种操作也是这样。

    而对于第一种操作,我们就是要处理出 所有 0和1 在原序列中的值,这个就可以用之前处理的前缀和来完成。

    三种操作都有一点点小的细节要考虑。

    dls niub!

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=200010;
    const int inf=0x3f3f3f3f;
    ll a[maxn];
    struct node{
        ll sum,lazy;
    }tr[maxn<<2];
    int n,q,pa,pb;
    ll x,prea[maxn],preb[maxn]; 
    void init(){
        pa=0,pb=0;
    }
    void build(int o,int l,int r){
        if(l==r){
            tr[o].sum=a[l];
            tr[o].lazy=-1;
            return ;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build((o<<1)|1,mid+1,r);
        tr[o].sum=tr[o<<1].sum+tr[(o<<1)|1].sum;
        tr[o].lazy=-1;
    }
    void pushup(int o){
        tr[o].sum=tr[o<<1].sum+tr[o<<1|1].sum;
    }
    void pushdown(int o,int l,int r){
        if(tr[o].lazy!=-1){
            tr[o<<1].lazy=tr[o].lazy;
            tr[o<<1|1].lazy=tr[o].lazy;
            int mid=(l+r)>>1;
            tr[o<<1].sum=tr[o].lazy*(mid-l+1);
            tr[o<<1|1].sum=tr[o].lazy*(r-mid);
            tr[o].lazy=-1;
        }
    }
    void update(int o,int l,int r,int ql,int qr,ll val){
        if(ql<=l&&r<=qr){
            tr[o].lazy=val;
            tr[o].sum=val*(r-l+1);
            return;
        }
        pushdown(o,l,r);
        int mid=l+((r-l)>>1);
        if(ql<=mid)update(o<<1,l,mid,ql,qr,val);
        if(qr>=mid+1)update(o<<1|1,mid+1,r,ql,qr,val);
        pushup(o);
    }
    ll query(int o,int l,int r,int ql,int qr){
        if(ql<=l&&qr>=r)return tr[o].sum;
        pushdown(o,l,r);
        int mid=(l+r)>>1;
        ll ans=0;
        if(ql<=mid)ans=query(o<<1,l,mid,ql,qr);
        if(qr>=mid+1)ans+=query(o<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    int op,u,v;
    int main(){
        while(cin>>n>>q>>x){
            init();
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i]);
                if(a[i]<=x){
                    prea[++pa]=a[i];
                    prea[pa]+=prea[pa-1];
                    a[i]=0;
                }else{
                    preb[++pb]=a[i];
                    preb[pb]+=preb[pb-1];
                    a[i]=1;
                }
            }
            build(1,1,n);
            while(q--)
            {
                scanf("%d%d%d",&op,&u,&v);
                if(op==2){
                    ll tep=query(1,1,n,u,v);
                    tep=v-u+1-tep;
                    if(tep>0)
                    update(1,1,n,u,u+tep-1,0);
                    if(tep<v-u+1)
                    update(1,1,n,u+tep,v,1);
                }else if(op==1){
                    if(u==1){
                        ll tp=query(1,1,n,u,v);
                        ll ans=preb[tp];
                        ans+=prea[v-tp];
                        printf("%lld
    ",ans);
                        continue;
                    }
                    ll tp1=query(1,1,n,1,u-1);
                    ll tp2=query(1,1,n,1,v);
                    ll ans=preb[tp2]-preb[tp1];
                    tp1=u-1-tp1,tp2=v-tp2;
                    ans+=prea[tp2]-prea[tp1];
                    printf("%lld
    ",ans);
                }else{
                    ll tep=query(1,1,n,u,v);
                    if(tep>0)
                    update(1,1,n,u,u+tep-1,1);
                    if(tep<v-u+1)
                    update(1,1,n,u+tep,v,0);
                }
            }
        }
    }
    View Code

    J Special Judge

    Code:zz

    Thinking:zz

    题意:给出一张图,求图中相交的线段的对数。

    m只有2000,直接m*m暴力判断就好了,本来以为套个板子就能ac,结果有很多小细节没考虑就wa了。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn = 0x3f3f3f3f;
    using namespace std;
    struct Point
    {
        long long x;
        long long y;
    };
    typedef struct Point point;
    long long multi(point p0, point p1, point p2)
    {
        //return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
        if((p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y) > 0)
        {
            return 1;
        }
        if((p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y) < 0)
        {
            return -1;
        }
        return 0;
    }
    bool isIntersected(point s1, point e1, point s2, point e2)
    {
        return    (max(s1.x, e1.x) >= min(s2.x, e2.x)) && (max(s2.x, e2.x) >= min(s1.x, e1.x)) &&
            (max(s1.y, e1.y) >= min(s2.y, e2.y)) &&
            (max(s2.y, e2.y) >= min(s1.y, e1.y)) && (multi(s1, s2, e1)*multi(s1, e1, e2)>=0) && (multi(s2, s1, e2)*multi(s2, e2, e1)>=0);
    }
    struct s
    {
        int a,b;
    }z[2020];
    int main(void)
    {
        int n,m,i,j,ans;
        while(~scanf("%d %d",&n,&m))
        {
            point po[2020];
            for(i = 0;i < m;i++)
            {
                scanf("%d %d",&z[i].a,&z[i].b);
            }
            for(i = 1;i <= n;i++)
            {
                scanf("%lld %lld",&po[i].x,&po[i].y);
            }
            ans = 0;
            for(i = 0;i < m;i++)
            {
                for(j = i + 1;j < m;j++)
                {
                    if(po[z[i].a].x == po[z[j].a].x && po[z[i].a].y == po[z[j].a].y || 
                    po[z[i].a].x == po[z[j].b].x && po[z[i].a].y == po[z[j].b].y || 
                    po[z[i].b].x == po[z[j].a].x && po[z[i].b].y == po[z[j].a].y || 
                    po[z[i].b].x == po[z[j].b].x && po[z[i].b].y == po[z[j].b].y)
                    {
                        if((po[z[i].a].x - po[z[i].b].x) * (po[z[j].a].y - po[z[j].b].y) == 
                        (po[z[i].a].y - po[z[i].b].y) * (po[z[j].a].x - po[z[j].b].x))
                        {
                            if((po[z[i].a].x == po[z[j].a].x && po[z[i].a].y == po[z[j].a].y
                            && (po[z[i].b].x - po[z[i].a].x) * (po[z[j].b].x - po[z[i].a].x) >= 0
                            || po[z[i].a].x == po[z[j].b].x && po[z[i].a].y == po[z[j].b].y
                            && (po[z[i].b].x - po[z[i].a].x) * (po[z[j].a].x - po[z[i].a].x) >= 0
                            || po[z[i].b].x == po[z[j].a].x && po[z[i].b].y == po[z[j].a].y
                            && (po[z[i].a].x - po[z[i].b].x) * (po[z[j].b].x - po[z[i].b].x) >= 0
                            ||po[z[i].b].x == po[z[j].b].x && po[z[i].b].y == po[z[j].b].y
                            && (po[z[i].a].x - po[z[i].b].x) * (po[z[j].a].x - po[z[i].b].x) >= 0)
                            && (po[z[i].a].y == po[z[i].b].y))
                            {
                                ans++;
                            }
                            else if((po[z[i].a].x == po[z[j].a].x && po[z[i].a].y == po[z[j].a].y
                            && (po[z[i].b].y - po[z[i].a].y) * (po[z[j].b].y - po[z[i].a].y) >= 0
                            || po[z[i].a].x == po[z[j].b].x && po[z[i].a].y == po[z[j].b].y
                            && (po[z[i].b].y - po[z[i].a].y) * (po[z[j].a].y - po[z[i].a].y) >= 0
                            || po[z[i].b].x == po[z[j].a].x && po[z[i].b].y == po[z[j].a].y
                            && (po[z[i].a].y - po[z[i].b].y) * (po[z[j].b].y - po[z[i].b].y) >= 0
                            ||po[z[i].b].x == po[z[j].b].x && po[z[i].b].y == po[z[j].b].y
                            && (po[z[i].a].y - po[z[i].b].y) * (po[z[j].a].y - po[z[i].b].y) >= 0)
                            && (po[z[i].a].x == po[z[i].b].x))
                            {
                                ans++;
                            }
                            else if((po[z[i].a].x == po[z[j].a].x && po[z[i].a].y == po[z[j].a].y
                            && (po[z[i].b].y - po[z[i].a].y) * (po[z[j].b].y - po[z[i].a].y) >= 0
                            || po[z[i].a].x == po[z[j].b].x && po[z[i].a].y == po[z[j].b].y
                            && (po[z[i].b].y - po[z[i].a].y) * (po[z[j].a].y - po[z[i].a].y) >= 0
                            || po[z[i].b].x == po[z[j].a].x && po[z[i].b].y == po[z[j].a].y
                            && (po[z[i].a].y - po[z[i].b].y) * (po[z[j].b].y - po[z[i].b].y) >= 0
                            ||po[z[i].b].x == po[z[j].b].x && po[z[i].b].y == po[z[j].b].y
                            && (po[z[i].a].y - po[z[i].b].y) * (po[z[j].a].y - po[z[i].b].y) >= 0))
                            {
                                ans++;
                            }
                        }
                        continue;
                    }
                    bool flag = isIntersected(po[z[i].a],po[z[i].b],po[z[j].a],po[z[j].b]);
                    if(flag)
                    {
                        //printf("%d %d  %d %d
    ",z[i].a,z[i].b,z[j].a,z[j].b);
                        ans++;
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    赛后总结:

    kk:今天开局以为几何题是板子题,眉头一皱发现事情并不简单,就看h题去了,结果智障的没有思路,pai爷一点拨就想通了,后来f题也在和pai爷的合作下写完了,感觉今天状态有点迷吧,还好代码都是一发ac的,以后不要再在h题这种简单题上卡了,加油。

    pai爷:今天浑水摸鱼,想尝试几道数列的题,奈何水平不够都咕了。

    zz:今天上来就发现两道签到题,稍微想了一下就知道该怎么做了,然后想了h,傻了,居然没想出来,队友有了思路以后就给队友去写了,然后看了几何题,题目感觉题目简单的,套个板子改改就好了,虽然通过率感人,但还是再测了几个样例以后就交了,果然wa了,发现少考虑了好多情况,最后想了好久,wa了5发才过(这场比赛我们队一共就wa了5发,我菜爆了)。

  • 相关阅读:
    oracle数据库中的单行函数
    Oracle数据库的基本语句
    oracle数据库安装的注意事项
    第一个自动化脚本
    负载均衡__笔记
    计算机名词解释
    开发规范__笔记
    索引_笔记
    主从复制_笔记
    Eclipse Git和sourceTree用法
  • 原文地址:https://www.cnblogs.com/mountaink/p/10317607.html
Copyright © 2020-2023  润新知