zoukankan      html  css  js  c++  java
  • 【20170521校内模拟赛】热爱生活的小Z

    学长FallDream所出的模拟赛,个人感觉题目难度还是比较适中的,难度在提高+左右,可能比较接近弱省省选,总体来讲试题考查范围较广,个人认为还是很不错的。
    所有试题如无特殊声明,开启-O2优化,时限1s,内存上限为128MB

    T1(seq)小Z爱序列

    题意简析

    给出一个1~n的全排列,问有多少对((i,j))满足(a_{i}<max( a_{[i+1,j-1]} ) < a_{j})

    数据范围及约定

    (1<=n<=10^6)

    解题思路

    通过观察,我们可以发现,答案在从右向左更新时,在某处的贡献为其右侧大于其的数的数量,故考虑使用单调栈维护右侧数单调性,每次先入队再计算贡献即可。
    总复杂度为(O(n) / O(n))

    #include <stdio.h>
    #define MN 1000005
    #define r register
    #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++)
    char BB[1<<15],*S=BB,*TT=BB;
    inline int in(){
        r int x; r bool f; r char c;
        for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
        for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
        return f?-x:x;
    }
    int n,ma,x,pos=1,a[MN],t,que[MN];
    long long ans;
    int main(){
        n=in();for (r int i=1; i<=n; ++i) a[i]=in();
        for (r int i=n; i; --i){
            while (a[i]>que[t]&&t) --t;
            que[++t]=a[i];if (t>2) ans+=t-2ll;
        }printf("%lld",ans);
    }
    

    T2(graph)小Z爱图论

    题意简析

    给定一张有向图,求有多少点对((i,j))满足从(i)是可达(j)的.

    数据范围及约定

    (1<=n<=2*10^3,1<=i,j<=n)

    解题思路

    考虑使用floyd解决连通性问题,发现可以通过bitset优化效率,故可以通过此题.
    总复杂度为$O(n^{3}/32) / O(n^2) $

    #include <stdio.h>
    #include <bitset>
    #define MN 2005
    #define r register
    #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),S==TT)?EOF:*S++)
    char BB[1<<15],*S=BB,*TT=BB;
    using std::bitset;
    inline int read(){
    	r int x; r bool f; r char c;
    	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
    	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
    	return f?-x:x;
    }
    bitset<MN> b[MN];int n,ans;
    int main(){
    	n=read();for (r int i=1; i<=n; ++i)
    		for (r int j=1; j<=n; ++j)
    			b[i][j]=(read()|(i==j));
    	for (r int k=1; k<=n; ++k)
    		for (r int i=1; i<=n; ++i)
    			if (b[i][k]) b[i]|=b[k];
    	for (r int i=1; i<=n; ++i) ans+=b[i].count();
    	printf("%d",ans);
    }
    

    T3(boat)小Z爱划水

    题意简析

    (n)个人,每个人可以选择划水或学习,有(m)对朋友关系,每个人有自己想做的事。
    有2种情况会使得整个朋友圈的不满意度+1
    1.一个人选择了自己不想做的事
    2.一对朋友做了不同的事
    求最小不满意度。

    数据范围及约定

    (1<=n<=3*10^2,1<=m<=n*(n+1)/2)

    解题思路

    容易发现,这是一个经典的网络流模型,对于选择了划水的人,我们将其割至源点,对于选择了学习的人,我们将其割至汇点,显然题意就是求最小割。
    具体建图方式如下:
    1)喜欢划水的,向源点连一条容量为1的边;
    2)喜欢学习的,向汇点连一条容量为1的边;
    3)在朋友关系间,互连一条容量为1的边;
    对上图求最小割即为本体正解。
    总复杂度为$O(Maxflow(n,n^2)) / O(n^2) $

    #include <stdio.h>
    #include <string.h>
    #define r register
    #define S 0
    #define T 301
    #define MN 305
    #define ME 100005
    #define inf 0x3f3f3f3f
    #define min(a,b) ((a)<(b)?(a):(b))
    #define getchar() (SS==TT&&(TT=(SS=BB)+fread(BB,1,1<<15,stdin),TT==SS)?EOF:*SS++)
    char BB[1<<15],*SS=BB,*TT=BB;
    inline int in(){
        r int x; r bool f; r char c;
        for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
        for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
        return f?-x:x;
    }
    struct node{int to,nxt,v;}edge[ME];
    int head[MN],lev[MN],n,m,cnt=1,que[MN],iter[MN];
    inline void ins(int x,int y,int f){edge[++cnt]=(node){y,head[x],f};head[x]=cnt;}
    inline void insw(int x,int y,int f){ins(x,y,f);ins(y,x,0);}
    inline bool bfs(){
        memset(lev,-1,sizeof(lev));
        r int h=0,t=1;que[1]=S;lev[S]=0;
        while(h<t){
            r int u=que[++h];
            for (r int i=head[u]; i; i=edge[i].nxt)
                if (lev[edge[i].to]==-1&&edge[i].v){
                    r int v=edge[i].to;lev[v]=lev[u]+1;
                    que[++t]=v;
                }
        }
        memcpy(iter,head,sizeof(head));
        return lev[T]!=-1;
    }
    int dfs(int u,int v,int f){
        if (u==v) return f;
        r int used=0;
        for (r int &i=iter[u]; i; i=edge[i].nxt)
            if (lev[edge[i].to]==lev[u]+1&&edge[i].v){
                r int w=dfs(edge[i].to,v,min(f-used,edge[i].v));
                used+=w;edge[i].v-=w;edge[i^1].v+=w;
                if (used==f) return f;
            }
        if (!used) lev[u]=-1;return used;
    }
    int dinic(){
        r int flow=0;
        while(bfs()){
            r int nf=dfs(S,T,inf);
            while(nf) flow+=nf,nf=dfs(S,T,inf); 
        }return flow;
    }
    void init(){
        n=in(),m=in();for (r int i=1; i<=n; ++i) in()?insw(S,i,1):insw(i,T,1);
        for (r int i=1; i<=m; ++i){r int x=in(),y=in();ins(x,y,1);ins(y,x,1);}
    }
    int main(){init(); printf("%d",dinic()); return 0;}
    

    T4(math)小Z爱数学

    题意简析

    定义函数(f(n,k))表示(n)的所有因数(p_{i})中满足(n/p_{i}<=k)(p_{i})的和。
    (Sigma_{i=1}^{n} f(i,k)) 有多组询问。

    数据范围及约定

    (询问数1<=m<=5*10^5,1<=n,k<=10^5)

    解题思路

    显然,如果不考虑(k)的限制,对于一个正整数(x),(x)的贡献为全体(x)的倍数,并且我们容易发现(f(n,k))(n)一定时,随(k)单调递增,故考虑对询问按(k)排序。
    接下来对于每次询问,统计所有在(max(n))范围内的所有满足当前(k)限制的贡献后计算答案,显然使用线段树是可以较为方便的实现这一操作的。
    考虑对([1,n])开一棵线段树统计当前的(f(i,k))然后维护即可。
    根据调和级数,我们有$$1+frac{1}{2}+frac{1}{3}+...+frac{1}{n} approx ln {n}$$
    故时间复杂度为(O(nln n log_{2} n +mlog_{2}nm))空间复杂度为(O(m+n)).

    #include <stdio.h>
    #include <algorithm>
    #define r register
    #define ll long long
    #define MN 500005
    #define M (1<<17)
    #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++)
    char BB[1<<15],*S=BB,*TT=BB;
    inline int in(){
        r int x; r bool f; r char c;
        for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
        for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
        return f?-x:x;
    }
    struct node{
    	int n,k,id;
    	inline bool operator <(const node &b){
    		return k<b.k;
    	}
    }q[MN];
    ll T[M<<1],ans[MN];int n;
    inline void A(int k,int v){for (k+=M; k; k>>=1) T[k]+=v;}
    inline ll Q(int L,int R){
    	r ll res=0;
    	for (L+=M-1,R+=M+1; L^R^1; L>>=1,R>>=1){
    		if (~L&1) res+=T[L^1];
    		if (R&1) res+=T[R^1]; 
    	}return res;
    }
    inline void update(int k){for (r int i=M/k; i; --i) A(i*k,i);}
    int main(){
    	n=in();
    	for (r int i=1; i<=n; ++i) q[i].n=in(),q[i].k=in(),q[i].id=i;
    	std::sort(q+1,q+n+1);for (r int i=1,j=0; i<=n; ++i){
    		while(j<q[i].k) update(++j);
    		ans[q[i].id]=Q(1,q[i].n);
    	}
    	for (r int i=1; i<=n; ++i) printf("%lld
    ",ans[i]);
    }
    
  • 相关阅读:
    利用qt打开一张图片并转成灰度矩阵
    适配手机端浏览器
    ps常用快捷键(供自己学习查看)
    用选框工具画圆角矩形
    ps制作有背景图片的字体
    所有iOS 设备的屏幕尺寸
    九宫格有规律高亮滚动效果
    移动端点击事件全攻略
    移动端ios升级到11及以上时,手机弹框输入光标出现错位问题
    linux下截取整个网页
  • 原文地址:https://www.cnblogs.com/Melacau/p/20170521test.html
Copyright © 2011-2022 走看看