zoukankan      html  css  js  c++  java
  • # 8.19考试总结

    8.19考试总结

    预计得分:230 实际得分:180 丢分:50

    真的是哪题不拍挂哪题

    T1

    方差的式子是

    [frac{sum a_i^2}{n} - frac{(sum a_i)^2}{n^2} ]

    题目中式子其实要求的是

    [nsum a_i^2-(sum a_i)^2 ]

    想DP发现这两个东西不好同时搞

    我们就DP一维记录一维

    记录肯定考虑记录值域最小的

    我们就设(f_{i,j,k})他去表示

    到了((i,j))这个点

    (sum a_i)的值为(k)的最大的(sum a_i^2)

    转移显然

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<vector>
    #include<ctime>
    #include<cmath>
    #define LL long long
    #define pii pair<int,int>
    #define mk make_pair
    #define fi first
    #define se second
    using namespace std;
    const int N = 35;
    const int M = 1835;
    int f[N][N][M];
    int a[N][N];
    int n,m;int num = 0;
    inline int read(){
    	int v = 0,c = 1;char ch = getchar();
    	while(!isdigit(ch)){
    		if(ch == '-') c = -1;
    		ch = getchar();
    	}
    	while(isdigit(ch)){
    		v = v * 10 + ch - 48;
    		ch = getchar();
    	}
    	return v * c;
    }
    int main(){
    //	freopen("path.in","r",stdin);
    	int T = read();
    	while(T--){
    		memset(f,0x3f,sizeof(f));
    		n = read(),m = read();
    		for(int i = 1;i <= n;++i)
    			for(int j = 1;j <= m;++j) a[i][j] = read();//cout << "GG" << endl;
    	//	memset(f,0x3f,sizeof(f));
    		f[1][1][a[1][1]] = a[1][1] * a[1][1];
    		for(int i = 1;i <= n;++i){
    			for(int j = 1;j <= m;++j){
    				for(int k = 0;k <= (i + j - 1) * 30;++k){
    					if(k + a[i + 1][j] <= (i + j) * 30) f[i + 1][j][k + a[i + 1][j]] = min(f[i + 1][j][k + a[i + 1][j]],
    					f[i][j][k] + a[i + 1][j] * a[i + 1][j]);
    					if(k + a[i][j + 1] <= (i + j) * 30) f[i][j + 1][k + a[i][j + 1]] = min(f[i][j + 1][k + a[i][j + 1]],
    					f[i][j][k] + a[i][j + 1] * a[i][j + 1]);  
    //					if(k + a[i + 1][j] > (i + j) * 30)		
    				}
    			}
    		}
    		LL ans = 0x3f3f3f3f;
    		for(int i = 0;i <= 1800;++i)  ans = min(ans,1ll * (n + m - 1) * f[n][m][i] - i * i);
    		 
    		printf("Case #%d: %lld
    ",++num,ans);
    	}
    	return 0;
    }
    
    

    T2

    挂烂了QAQ

    考虑优雅的暴力建边

    mGVXpF.png

    这是暴力建边方式时间复杂度(O(nm))

    正确性显然

    发现每次都是一个点向一个区间连边,直接线段树优化这个过程

    而由于边权只有(1/0)

    最短路径可以(01)bfs

    关于线段树优化建图的本质,这里就简单的说一下

    本质是维护了两颗线段树,一颗表示入边另外一颗表示出边

    区间操作就可以通过虚点来进行连接

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<vector>
    #include<ctime>
    #include<cmath>
    #include<deque>
    #define LL long long
    #define pii pair<int,int>
    #define mk make_pair
    #define fi first
    #define se second
    using namespace std;
    const int N = 1e6 + 3;
    int pos[N];
    int n,m,s;
    int whe;
    struct tree{
    	int head[N << 2];
    	int dis[N << 2];
    	int rt1,rt2,tot,t;
    	struct node{
    		int lc;
    		int rc;
    	}a[N << 2];
    	struct edge{
    		int to;
    		int nxt;
    		int data;
    	}e[N * 35];
    	inline void add(int x,int y,int z){
    		e[++tot].to = y;
    		e[tot].data = z;
    		e[tot].nxt = head[x];
    		head[x] = tot;
    	}
    	inline void build(int &u,int l,int r,bool flag){
    		if(!u) u = ++t;
    		if(l == r) {if(!flag) pos[l] = u;return;}
    		int mid = (l + r) >> 1;
    		build(a[u].lc,l,mid,flag);build(a[u].rc,mid + 1,r,flag);
    		if(flag){
    			add(a[u].lc,u,0);
    			add(a[u].rc,u,0);	
    		}
    		else{
    			add(u,a[u].lc,0);
    			add(u,a[u].rc,0);	
    		}
    	}
    	inline void updata(int u,int l,int r,int ll,int rr,int p,bool flag){
    		if(l == ll && r == rr){
    			if(flag) add(u,p,0);
    			else add(p,u,0);
    			return ;
    		}
    		int mid = (l + r) >> 1;
    		if(rr <= mid) updata(a[u].lc,l,mid,ll,rr,p,flag);
    		else if(ll > mid) updata(a[u].rc,mid + 1,r,ll,rr,p,flag);
    		else{
    			updata(a[u].lc,l,mid,ll,mid,p,flag);
    			updata(a[u].rc,mid + 1,r,mid + 1,rr,p,flag);
    		}
    	}
    	inline void ADD(int r1,int r2,int l,int r){
    		if(l == r){
    			add(r2,r1,0);
    			return ; 
    		}
    		int mid = (l + r) >> 1;
    		ADD(a[r1].lc,a[r2].lc,l,mid);ADD(a[r1].rc,a[r2].rc,mid + 1,r);
    	}
    	inline void link(int l,int r,int ll,int rr){
    		updata(rt1,1,n,l,r,++t,1);
    		updata(rt2,1,n,ll,rr,++t,0);
    		add(t - 1,t,1);	
    	}
    	inline void bfs(int x){
    		memset(dis,0x3f,sizeof(dis));
    		dis[x] = 0;
    		deque <int> q;
    		q.push_back(x);
    		while(!q.empty()){
    			int k = q.front();
    			q.pop_front();
    			for(int i = head[k];i;i = e[i].nxt){
    				int y = e[i].to;		
    				if(dis[y] > dis[k] + e[i].data){
    					dis[y] = dis[k] + e[i].data;
    					if(e[i].data) q.push_back(y);
    					else q.push_front(y);	
    				}
    			}
    		}
    		for(int i = 1;i <= n;++i) printf("%d
    ",dis[pos[i]]);
    	}
    }T;
    inline int read(){
    	int v = 0,c = 1;char ch = getchar();
    	while(!isdigit(ch)){
    		if(ch == '-') c = -1;
    		ch = getchar();
    	}
    	while(isdigit(ch)){
    		v = v * 10 + ch - 48;
    		ch = getchar();
    	}
    	return v * c;
    }
    int main(){
    	n = read(),m = read(),s = read();
    	T.build(T.rt1,1,n,1);
    	T.build(T.rt2,1,n,0);
    	T.ADD(T.rt1,T.rt2,1,n);
    	for(int i = 1;i <= m;++i){
    		int l = read(),r = read(),ll = read(),rr = read();
    		T.link(l,r,ll,rr);
    		T.link(ll,rr,l,r);
    	}
    //	printf("%d
    ",pos[s]);
    	T.bfs(pos[s]);
    	return 0;
    }
    
    

    T3

    (n = 1000)被我(n^3)卡过去了可还行

    我到现在还是怀疑题解的思路是错的,

    说一下另外一个(n^2)做法

    把矩阵查分两次之后

    就变成了求最大的全(0)子矩阵(可能细节和边界要特殊处理)

    这个直接悬线法求就好了

  • 相关阅读:
    第三章web安全基础—IIS发布网站(其中包括服务器IIS搭建、DNS搭建)
    第三章web安全基础—web系统架构
    第二章网络协议安全—网络协议看安全
    第一章信息收集—漏洞利用框架metasploit基本实用
    第一章信息收集—漏洞扫描awvs和appscan
    第一章信息收集—扫描技术与抓包分析
    Pikachu——Unsafe Fileupload不安全文件上传
    Pikachu——Unsafe Filedownload 不安全的文件下载
    Pikachu——File Inclusion(文件包含)
    拿什么拯救你,红果果的小磁盘?
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/11381829.html
Copyright © 2011-2022 走看看