• 2011 Multi-University Training Contest 8


    Rank:56/147.

    开场看B,是个线段树区间合并,花了2hour敲完代码。。。再花了30min查错。。发现push_down有问题。改了就AC了。

    然后发现A过了很多人。推了个公式,发现是个分段函数。取个中间点代进去结果就AC了。

    C好像也很水?看了看原来是个傻逼BFS。A了。

    F化解了一下就 集合子集异或为0的种数。想了想没想到什么东西就go die了。

    A.Liang Guo Sha(阅读理解)

    看懂题意后搞出两个式子,然后取个极值就行了。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        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;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    //Code begin...
    
    int main ()
    {
        int a, b, c;
        while (~scanf("%d%d%d",&a,&b,&c)){
            double p=((b+c)*1.0)/(a+b+2*c);
            double ans=a*p*p+b*(1-p)*(1-p)-c*(1-p)*p*2;
            printf("%.6f
    ",ans);
        }
        return 0;
    }
    View Code

    B.Black And White(线段树)

    询问区间[l,r]的最长连续黑色的长度。

    建立线段树,对每个节点维护6个量,分别表示最长连续黑色,最长连续白色,左边最长连续黑色,左边最长连续白色,右边最长连续黑色,右边最长连续白色。

    对于修改操作用tag标记一下。在需要push_down的时候push_down即可AC。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        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;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    //Code begin...
    
    struct SegTree{int lbmax, lwmax, rbmax, rwmax, bmax, wmax;}seg[N<<2];
    struct Node{
        int lmax, rmax, ma, siz;
        Node(int _lmax=0, int _rmax=0, int _ma=0, int _siz=0):lmax(_lmax), rmax(_rmax), ma(_ma), siz(_siz){}
    };
    int a[N];
    bool tag[N<<2];
    
    void push_up(int p, int l, int r){
        int lsize=(l+r)/2-l+1, rsize=r-(l+r)/2;
        if (seg[p<<1].lbmax) {
            seg[p].lbmax=(seg[p<<1].lbmax==lsize?seg[p<<1|1].lbmax:0)+seg[p<<1].lbmax;
            seg[p].lwmax=0;
        }
        else {
            seg[p].lwmax=(seg[p<<1].lwmax==lsize?seg[p<<1|1].lwmax:0)+seg[p<<1].lwmax;
            seg[p].lbmax=0;
        }
        if (seg[p<<1|1].rbmax) {
            seg[p].rbmax=(seg[p<<1|1].rbmax==rsize?seg[p<<1].rbmax:0)+seg[p<<1|1].rbmax;
            seg[p].rwmax=0;
        }
        else {
            seg[p].rwmax=(seg[p<<1|1].rwmax==rsize?seg[p<<1].rwmax:0)+seg[p<<1|1].rwmax;
            seg[p].rbmax=0;
        }
        seg[p].bmax=max(max(seg[p<<1].bmax,seg[p<<1|1].bmax),seg[p<<1].rbmax+seg[p<<1|1].lbmax);
        seg[p].wmax=max(max(seg[p<<1].wmax,seg[p<<1|1].wmax),seg[p<<1].rwmax+seg[p<<1|1].lwmax);
    }
    void push_down(int p){
        if (!tag[p]) return ;
        tag[p<<1]^=1; tag[p<<1|1]^=1; tag[p]=0;
        swap(seg[p].bmax,seg[p].wmax); swap(seg[p].lbmax,seg[p].lwmax); swap(seg[p].rbmax,seg[p].rwmax);
    }
    void init(int p, int l, int r){
        if (l<r) {
            int mid=(l+r)>>1;
            init(lch); init(rch); push_up(p,l,r); tag[p]=0;
        }
        else {
            if (a[l]) seg[p].lbmax=seg[p].rbmax=seg[p].bmax=1, seg[p].lwmax=seg[p].rwmax=seg[p].wmax=0;
            else seg[p].lwmax=seg[p].rwmax=seg[p].wmax=1, seg[p].lbmax=seg[p].rbmax=seg[p].bmax=0;
            tag[p]=0;
        }
    }
    void update(int p, int l, int r, int L, int R){
        push_down(p);
        if (L>r||R<l) return ;
        if (L<=l&&R>=r) tag[p]=1, push_down(p);
        else {
            int mid=(l+r)>>1;
            update(lch,L,R); update(rch,L,R); push_up(p,l,r);
        }
    }
    Node query(int p, int l, int r, int L, int R){
        push_down(p);
        if (L>r||R<l) return Node(0,0,0,0);
        if (L<=l&&R>=r) return Node(seg[p].lbmax,seg[p].rbmax,seg[p].bmax,r-l+1);
        int mid=(l+r)>>1;
        Node x=query(lch,L,R), y=query(rch,L,R), z;
        z.lmax=(x.lmax==x.siz?y.lmax:0)+x.lmax; z.rmax=(y.rmax==y.siz?x.rmax:0)+y.rmax;
        z.ma=max(max(x.ma,y.ma),x.rmax+y.lmax); z.siz=x.siz+y.siz;
        return z;
    }
    int main ()
    {
        int n, m, flag, l, r;
        while (~scanf("%d",&n)) {
            FOR(i,1,n) scanf("%d",a+i);
            init(1,1,n);
            scanf("%d",&m);
            FOR(i,1,m) {
                scanf("%d%d%d",&flag,&l,&r);
                if (flag) update(1,1,n,l,r);
                else {
                    printf("%d
    ",query(1,1,n,l,r).ma);
                }
            }
        }
        return 0;
    }
    View Code

    C.Turn Right(BFS)

    题目保证一定存在起点到终点的路径。如果把终点给封死,那么从起点bfs一次再回到起点就行了。沿途统计所有标记。

    这题的节点状态与普通的不同,需要定义vis[i][j]表示到点i是以j方向到的。然后对于每个方向会有一个优先级。即总是turn right。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        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;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=505;
    //Code begin...
    
    int vis[N][N][4], row[N][N], col[N][N];
    int ps[4][4]={{3,0,1,2},{0,1,2,3},{1,2,3,0},{2,3,0,1}};
    
    struct Node{
        int x, y, pos;
        Node(int _x=0, int _y=0, int _pos=0):x(_x),y(_y),pos(_pos){}
    };
    queue<Node>Q;
    
    int main ()
    {
        int T, n, m, s, t;
        scanf("%d",&T);
        while (T--) {
            int num=0;
            mem(vis,0);
            scanf("%d%d%d%d",&n,&m,&s,&t);
            FOR(i,1,2*n-1) {
                if (i&1) FO(j,0,m-1) scanf("%d",&col[(i-1)/2][j]);
                else FO(j,0,m) scanf("%d",&row[i/2][j]);
            }
            while (!Q.empty()) Q.pop();
            Q.push(Node(0,s,1)); vis[0][s][1]=1;
            while (!Q.empty()) {
                Node tmp=Q.front(); Q.pop();
                FO(i,0,4) {
                    int now=ps[tmp.pos][i];
                    if (now==0) {
                        if (tmp.y==0||col[tmp.x][tmp.y-1]) continue;
                        if (vis[tmp.x][tmp.y-1][now]) goto label;
                        Q.push(Node(tmp.x,tmp.y-1,now));
                        vis[tmp.x][tmp.y-1][now]=1;
                        break;
                    }
                    else if (now==1) {
                        if (tmp.x==n-1||row[tmp.x+1][tmp.y]) continue;
                        if (vis[tmp.x+1][tmp.y][now]) goto label;
                        Q.push(Node(tmp.x+1,tmp.y,now));
                        vis[tmp.x+1][tmp.y][now]=1;
                        break;
                    }
                    else if (now==2) {
                        if (tmp.y==m-1||col[tmp.x][tmp.y]) continue;
                        if (vis[tmp.x][tmp.y+1][now]) goto label;
                        Q.push(Node(tmp.x,tmp.y+1,now));
                        vis[tmp.x][tmp.y+1][now]=1;
                        break;
                    }
                    else {
                        if (tmp.x==0||row[tmp.x][tmp.y]) continue;
                        if (vis[tmp.x-1][tmp.y][now]) goto label;
                        Q.push(Node(tmp.x-1,tmp.y,now));
                        vis[tmp.x-1][tmp.y][now]=1;
                        break;
                    }
                }
            }
    label:  FO(i,0,n) FO(j,0,m) FO(k,0,4) if (vis[i][j][k]) {++num; break;}
            puts(num==n*m?"YES":"NO");
        }
        return 0;
    }
    View Code

    F.Game(高斯消元)

    要想去除某些石堆使得先手必败。那么s[i]^s[i+1]^...s[n]=0.即问题转化为求出集合S的子集异或和为0的子集种数。

    集合S里的每个数,要么选要么不选,考虑每一位的贡献,那么选了这个数,这个数上二进制位为1的位会贡献1.

    于是对于每位,建立异或方程组,再用高斯消元求解这个方程的自由变元的数量即可。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        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;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=105;
    //Code begin...
    
    int equ, var, a[35][N];
    
    LL pow_mod(LL a, LL n, LL mod){
        LL ret=1, temp=a%mod;
        while (n) {
            if (n&1) ret=ret*temp%mod;
            temp=temp*temp%mod;
            n>>=1;
        }
        return ret;
    }
    int Guass(){
        int row, col;
        for(row=0,col=0; row<equ&&col<var; ++col,++row){
            int max_r=row;
            FO(i,row+1,equ) {
                if(a[row][col]==1) break;
                if(a[max_r][col]<a[i][col]){max_r=i; break;}
            }
            if(max_r!=row) FOR(j,0,var) swap(a[max_r][j],a[row][j]);
            if(a[row][col]==0) row--;
            FO(i,row+1,equ) {
                if(a[i][col]==0) continue;
                FOR(j,col,var) a[i][j]^=a[row][j];
            }
        }
        FO(i,row,equ) if(a[i][col]) return -1;
        return var-row;
    }
    int main ()
    {
        int T, n, val;
        scanf("%d",&T);
        while (T--) {
            mem(a,0);
            scanf("%d",&n);
            equ=31; var=n;
            FO(i,0,n) {
                scanf("%d",&val);
                FO(j,0,equ) a[j][i]=val%2, val/=2;
            }
            FO(j,0,equ) a[j][n]=0;
            int b=Guass();
            printf("%lld
    ",pow_mod(2,b,MOD));
        }
        return 0;
    }
    View Code

    G.Sequence Decomposition(贪心+树状数组)

    给出一个序列,每次可以将连续的一段都减去1,每次操作的长度定义为连续段的长度,问最后使得序列都变为0时,最短的操作长度最长是多少。

    首先,将操作改变顺序是不影响答案的。不妨从左端点1开始,依次向后看右端点的最佳选值.

    如果有a[i]<=a[i+1],那么右端点就可以从i拓展到i+1了。如果有a[i]>a[i+1].那么右端点就不能再继续拓展了。反证证明这个贪心的正确性。

    但是如果直接模拟操作的话显然是超时的。注意到每次的操作实际上是区间减,查询单点。可以用树状数组维护。

    复杂度O(nlogn).

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        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;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=10005;
    //Code begin...
    
    int a[N], tree[N], n;
    
    void add(int x, int val){while (x<=n+1) tree[x]+=val, x+=lowbit(x);}
    int query(int x){
        int res=0;
        while (x) res+=tree[x], x-=lowbit(x);
        return res;
    }
    int main ()
    {
        int T, ans;
        scanf("%d",&T);
        while (T--) {
            mem(tree,0); ans=INF;
            scanf("%d",&n);
            FOR(i,1,n) scanf("%d",a+i), add(i,a[i]), add(i+1,-a[i]);
            a[n+1]=0;
            int now=1;
            FOR(i,1,n) {
                if (a[i]<=a[i+1]) continue;
                int tmp=a[i]-a[i+1];
                add(now,-tmp); add(i+1,tmp);
                FOR(j,now,i) if (query(j)>=0) {ans=min(i-j+1,ans); now=j; break;}
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    H.Road constructions(最大权闭合子图)

    裸题。。。不明白考试为啥不看。。。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        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;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=5005;
    //Code begin...
    
    struct Edge{int p, next, w;}edge[500005];
    struct Node{int pre, suc, w, id;}node[3005];
    int head[N], cnt=2, s, t, vis[N];
    int val[N];
    queue<int>Q;
    
    void add_edge(int u, int v, int w){
        edge[cnt].p=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++;
        edge[cnt].p=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt++;
    }
    int bfs(){
        int i, v;
        mem(vis,-1);
        vis[s]=0; Q.push(s);
        while (!Q.empty()) {
            v=Q.front(); Q.pop();
            for (i=head[v]; i; i=edge[i].next) {
                if (edge[i].w>0 && vis[edge[i].p]==-1) {
                    vis[edge[i].p]=vis[v] + 1;
                    Q.push(edge[i].p);
                }
            }
        }
        return vis[t]!=-1;
    }
    int dfs(int x, int low){
        int i, a, temp=low;
        if (x==t) return low;
        for (i=head[x]; i; i=edge[i].next) {
            if (edge[i].w>0 && vis[edge[i].p]==vis[x]+1){
                a=dfs(edge[i].p,min(edge[i].w,temp));
                temp-=a; edge[i].w-=a; edge[i^1].w += a;
                if (temp==0) break;
            }
        }
        if (temp==low) vis[x]=-1;
        return low-temp;
    }
    void init(){mem(head,0); mem(val,0); cnt=2;}
    int main ()
    {
        int n, m, k;
        while (scanf("%d%d",&n,&m), n+m) {
            int res=0, sum=0, tmp;
            s=0; t=m+1; init();
            FOR(i,1,m) scanf("%d",&tmp), res+=tmp, add_edge(s,i,tmp);
            scanf("%d",&k);
            FOR(i,1,k) scanf("%d%d%d%d",&node[i].pre,&node[i].suc,&node[i].id,&node[i].w), val[node[i].id]+=node[i].w;
            FOR(i,1,k) FOR(j,i+1,k) {
                if (node[i].id==node[j].id) continue;
                if (node[i].suc==node[j].pre) add_edge(node[i].id,node[j].id,INF);
                else if (node[i].pre==node[j].suc) add_edge(node[j].id,node[i].id,INF);
            }
            FOR(i,1,m) add_edge(i,t,val[i]);
            while (bfs()) while (tmp=dfs(s,INF)) sum+=tmp;
            printf("%d
    ",res-sum);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    走进AngularJs(二) ng模板中常用指令的使用方式
    mysql知识汇总
    存储动态数据时,数据库的设计方法
    js判断密码强度
    svg―Raphael.js Library(一)
    常用js代码
    IE6实现图片或背景的圆角效果
    巧用css border
    IE6下的效果
    理解盒模型
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6727714.html
Copyright © 2020-2023  润新知