• 17.10.20


      • Time flies、、、
      • 上午
        • BOZJ 1057 [ZJOI2007]棋盘制作

    神奇悬线大法好、、、
    h[i][j]:(i,j)可以向上延伸多长
      转移:h[i][j]=(j!=1&&(mp[i][j]^mp[i-1][j]))?h[i-1][j]+1:1
    L[i][j]:(i,j)可以向左延伸多长
      转移:L[i][j]=(j!=1&&(mp[i][j]^mp[i][j-1]))?L[i][j-1]+1:1
    R[i][j]:(i,j)可以向右延伸多长
      转移:R[i][j]=(j!=n&&(mp[i][j]^mp[i][j+1]))?R[i][j+1]+1:1
       
    l[i][j]:以(i,j)为下底上的一点,h(i,j)为高的矩形可以向左延伸多长
      转移:l[i][j]=(i!=1&&(mp[i][j]^mp[i-1][j]))?min(L[i][j],l[i-1][j]):L[i][j]
    r[i][j]:以(i,j)为下底上的一点,h(i,j)为高的矩形可以向右延伸多长
      转移:r[i][j]=(i!=1&&(mp[i][j]^mp[i-1][j]))?min(R[i][j],r[i-1][j]):R[i][j]
       
    然后对于每个位置(i,j)
    以它为下底上的一点,h(i,j)为高的矩形面积 = h[i][j]*(r[i][j]+l[i][j]-1)
    至于正方形,面积 = min(h[i][j],r[i][j]+l[i][j]-1)*min(h[i][j],r[i][j]+l[i][j]-1)
           
    (转移还是很清晰的,但这个方法真的很666)

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 2005
    using namespace std;
    int mp[MAXN][MAXN];
    int h[MAXN][MAXN],l[MAXN][MAXN],r[MAXN][MAXN],L[MAXN][MAXN],R[MAXN][MAXN];
    int n,m,ans1,ans2;
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			scanf("%d",&mp[i][j]);
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++)
    			h[i][j]=(j!=1&&(mp[i][j]^mp[i-1][j]))?h[i-1][j]+1:1;
    		for(int j=1;j<=m;j++)
    			L[i][j]=(j!=1&&(mp[i][j]^mp[i][j-1]))?L[i][j-1]+1:1;
    		for(int j=m;j>=1;j--)
    			R[i][j]=(j!=n&&(mp[i][j]^mp[i][j+1]))?R[i][j+1]+1:1;
    		for(int j=1;j<=m;j++){
    			l[i][j]=(i!=1&&(mp[i][j]^mp[i-1][j]))?min(L[i][j],l[i-1][j]):L[i][j];
    			r[i][j]=(i!=1&&(mp[i][j]^mp[i-1][j]))?min(R[i][j],r[i-1][j]):R[i][j];
    			ans1=max(ans1,min(h[i][j],r[i][j]+l[i][j]-1)*min(h[i][j],r[i][j]+l[i][j]-1));
    			ans2=max(ans2,h[i][j]*(r[i][j]+l[i][j]-1));
    		}
    	} 
    	printf("%d
    %d",ans1,ans2);
    	return 0;
    }
    
        • lence选讲
      • 下午
        • BZOJ 1058 [ZJOI2007]报表统计

    stl大法好
    第一个可重集维护序列相邻两个元素的差值,
    插入元素时,先抹去插入位置的差值,在加入两个新的差值
       
    第二个可重集维护所有的元素,加入一个新元素时就取出比它小的和比它大的那两个元素
    ,更新答案。

    代码:

    #include<set>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 0x3f3f3f3f
    #define MAXN 500005
    #define siter set<int>::iterator
    using namespace std;
    multiset<int>s1,s2;
    int Begin[MAXN],End[MAXN];
    int ans1=INF,ans2=INF,n,m;
    void Getans2(int x){
    	siter si=s2.find(x),sj;
    	if(si!=s2.begin()) sj=si,sj--,ans2=min(ans2,x-(*sj));
    	sj=si; sj++; if(sj!=s2.end()) ans2=min(ans2,*(sj)-x);
    }
    int main(){
    	char s[15]; int a,b,len;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%d",&Begin[i]),End[i]=Begin[i];
    	for(int i=1;i<=n;i++){
    		if(i!=n) s1.insert(abs(Begin[i+1]-End[i]));
    		s2.insert(Begin[i]);
    		Getans2(Begin[i]);
    	}
    	for(int i=1;i<=m;i++){
    		scanf("%s",s); len=strlen(s);
    		if(len==6){
    			scanf("%d%d",&a,&b);
    			if(a!=n){
    				siter si=s1.find(abs(Begin[a+1]-End[a]));
    				s1.erase(si);
    				s1.insert(abs(Begin[a+1]-b));
    			}
    			s1.insert(abs(b-End[a])); End[a]=b;
    			s2.insert(b);
    			Getans2(b);
    		}
    		else if(len==7) {
    			ans1=*(s1.begin());
    			printf("%d
    ",ans1);
    		}
    		else if(len==12)
    			printf("%d
    ",ans2);
    	}	
    	return 0;
    }
    
        • lence又来?!
      • 晚上
        • BZOJ 1059 [ZJOI2007]矩阵游戏

    二分图匹配
    对于一个黑点(i,j)
    把点i向j+n连边,然后二分图匹配
    如果是完美匹配的话,则合法
    因为完美匹配选出来的那些点是行列各异的,一定可以调整到主对角线上去。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    struct edge{
    	int to,next;
    }e[200*200+50];
    int vis[405];
    int head[405],match[405];
    int n,T,ent,cnt,tim;
    void init(){
    	memset(head,0,sizeof(head));
    	memset(match,0,sizeof(match));
    	ent=2; cnt=0;
    }
    void add(int u,int v){
    	e[ent]=(edge){v,head[u]};
    	head[u]=ent++;
    }
    bool Find(int u){
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(vis[v]==tim) continue;
    		vis[v]=tim;
    		if(!match[v]||Find(match[v])){
    			match[v]=u;
    			return 1;
    		}
    	}
    	return 0;
    }
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		init(); int x;
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++)
    			for(int j=n+1;j<=2*n;j++){
    				scanf("%d",&x);
    				if(x) add(i,j);
    			}
    		for(int i=1;i<=n;i++){
    			tim++;
    			if(Find(i)) cnt++;
    		}
    		if(cnt==n) puts("Yes");
    		else puts("No");
    	}
    	return 0;
    }
    
        • BZOJ 1060 [ZJOI2007]时态同步

    贪心吧。
    最后大家都要达到的时间就是耗时最长的那个叶子的时间,因为增加最终时间的话代价只会更大。
    计算出每个叶子需要延长的时间 ,
    tim[i]表示i节点与fa[i]的边上预计增加的权值
    显然 对于 u节点的所有儿子v
    tim[u]=min(tim[v])
    上式的意思是u的儿子都需要增加某一权值的话,那就直接加给u和fa[u]那条边上。
    然后u的儿子v剩下的权值tim[v]-tim[u]就累计到ans,表示把剩下的权值放在v与u的那条边上。
     
    由于s(起点)无fa,所以特别的tim[u]=0

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define ll long long
    #define INF 0x3f3f3f3f3f3f3f3f
    #define MAXN 500005
    using namespace std;
    struct edge{
    	int to,val,next;
    }e[MAXN*2];
    int head[MAXN];
    ll tim[MAXN],ans,maxtime;
    int n,s,ent=2;
    void read(int &x){
    	static int f; static char ch;
    	x=0; f=1; ch=getchar();
    	while(ch<'0'||'9'<ch){if(ch=='-') f=-1;ch=getchar();}
    	while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	x*=f;
    }
    void add(int u,int v,int w){
    	e[ent]=(edge){v,w,head[u]};
    	head[u]=ent++;
    }
    void dfs1(int u,int fa,ll t){
    	if(!e[head[u]].next) tim[u]=t,maxtime=max(maxtime,t);	//叶子节点 
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa) continue;
    		dfs1(v,u,t+e[i].val);
    	}
    }
    void dfs2(int u,int fa){
    	if(!e[head[u]].next) tim[u]=maxtime-tim[u]; 		//叶子节点 
    	else tim[u]=(u==s)?0:INF;							//非叶子节点 
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa) continue;
    		dfs2(v,u);
    		tim[u]=min(tim[u],tim[v]);
    	}
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa) continue;
    		ans+=tim[v]-tim[u];
    	}
    }
    int main(){
    	read(n); read(s);
    	for(int i=1,a,b,c;i<n;i++) 
    		read(a),read(b),read(c),add(a,b,c),add(b,a,c);
    	dfs1(s,0,0);
    	dfs2(s,0);
    	printf("%lld",ans);
    	return 0;
    }

     

        • BZOJ 1061 [Noi2008]志愿者招募

    极好的题!!
    让我对网络流建图产生了一点新的感觉
    大佬详细题解,写得很好很详细,赞一个:
    https://www.byvoid.com/zhs/blog/noi-2008-employee

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define INF 0x3f3f3f3f
    using namespace std;
    struct edge{
    	int to,capo,cost,next;
    }e[30010];
    int head[1010];
    int n,m,ent=2,S,T;
    void add(int u,int v,int capo,int cost){
    	e[ent]=(edge){v,capo,cost,head[u]};
    	head[u]=ent++;
    	e[ent]=(edge){u,0,-cost,head[v]};
    	head[v]=ent++;
    }
    void Readin_Build(){
    	scanf("%d%d",&n,&m); 
    	S=n+2,T=n+3;
    	for(int i=1,last,now=0,w;i<=n+1;i++){
    		last=now; now=0;
    		if(i<=n) scanf("%d",&now);
    		w=now-last;
    		if(w>0) add(S,i,w,0);
    		else add(i,T,-w,0);
    	}
    	for(int i=1,l,r,w;i<=m;i++){
    		scanf("%d%d%d",&l,&r,&w);
    		add(l,r+1,INF,w);
    	}
    	for(int i=1;i<=n;i++)
    		add(i+1,i,INF,0);
    }
    bool spfa(int &Cost){
    	static bool inq[1010];
    	static int dis[1010],low[1010],p[1010];
    	queue<int>q;
    	memset(dis,0x3f,sizeof(dis));
    	q.push(S); inq[S]=1; dis[S]=0; low[S]=INF;
    	while(!q.empty()){
    		int u=q.front(); q.pop(); inq[u]=0;
    		for(int i=head[u];i;i=e[i].next){
    			if(!e[i].capo) continue;
    			int v=e[i].to;
    			if(dis[v]<=dis[u]+e[i].cost) continue;
    			dis[v]=dis[u]+e[i].cost;
    			low[v]=min(e[i].capo,low[u]);
    			p[v]=i;
    			if(!inq[v]) q.push(v),inq[v]=1;
    		}
    	}
    	if(dis[T]==INF) return 0;
    	Cost+=low[T]*dis[T];
    	int u=T;
    	while(u!=S){
    		e[p[u]].capo-=low[T];
    		e[p[u]^1].capo+=low[T];
    		u=e[p[u]^1].to;
    	}
    	return 1;
    }
    void Mincost_Maxflow(){
    	int Cost=0;
    	while(spfa(Cost));
    	printf("%d",Cost);
    }
    int main(){
    	Readin_Build();
    	Mincost_Maxflow();
    	return 0;
    }
    
  • 相关阅读:
    使用charles proxy for Mac来抓取手机App的网络包
    NProxy——Mac和Linux平台下的Fiddler
    NProxy——Mac和Linux平台下的Fiddler
    NProxy——Mac和Linux平台下的Fiddler
    【HTTP】Fiddler(二)
    ORA-12541: TNS: 无监听程序、监听程序当前无法识别连接描述符中请求的服务
    一些网站
    oracle 11g 创建普通用户
    ORACLE VARCHAR2
    LEFT JOIN , RIGHT JOIN ,INNER JOIN
  • 原文地址:https://www.cnblogs.com/zj75211/p/7701823.html
Copyright © 2020-2023  润新知