首页 > 其他分享 >codeforce 2000+练习

codeforce 2000+练习

时间:2023-03-13 22:47:45浏览次数:59  
标签:ch int 练习 up down 2000 codeforce ans include

Three Sequences 2200

https://www.luogu.com.cn/problem/CF1406D
题解:贪心地想,令x为答案,则x应该为b的末项和c的首项,而每一步a(i)->a(i+1)若上升则b上升,若下降则c下降。故2x-a1>=up,2x-an>=down,解方程组可得到x值。
对于每步操作,它会使得l-1->l和r->r+1的上升/下降值发生变化,我们可以用差分数列+树状数组维护这种变化,复杂度为O(qlogn)。
代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int a[N],c[N];

int ask(int x){
	int ans=0;
	for(;x;x-=x&-x) ans+=c[x];
	return ans;
}
void ad(int x,int w){
	for(;x<=1e5;x+=x&-x) c[x]+=w;
}
void add(int l,int r,int w){
	ad(l,w);ad(r+1,-w);
}
int suan(int x){
	if(x>=0) return (x+1)/2;
	else{
		return -((-x)/2);
	}
}
signed main(){
	int n;cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	int up=0,down=0;
	ad(1,a[1]);
	for(int i=2;i<=n;i++){
		int d=a[i]-a[i-1];
		ad(i,d);
		if(d>=0) up+=d;
		else down-=d;
	}
	up+=a[1],down+=a[n];
	int ans=max(suan(up),suan(down));
	cout<<ans<<endl;
	int q;cin>>q;
	for(int i=1;i<=q;i++){
		int l,r,w;cin>>l>>r>>w;
		if(l==1) up+=w;
		if(r==n) down+=w;
		if(w>=0){
			if(l!=1){
				int e=ask(l)-ask(l-1);
				if(e<0&&e+w>=0)
				down+=e,up+=e+w;
				else if(e<0&&e+w<0)
				down+=e,down-=e+w;
				else if(e>=0)
				up+=w;
			}
			if(r!=n){
				int e=ask(r+1)-ask(r);
				if(e>=0&&e-w<0){
					up-=e;down-=e-w;
				}
				else if(e>=0&&e-w>=0) up-=e,up+=e-w;
				else if(e<0) down-=-(e),down+=-(e-w);
			}
		}
		else{
			if(l!=1){
				int e=ask(l)-ask(l-1);
				if(e>=0&&e+w<0)
				up-=e,down+=-(e+w);
				else if(e>=0&&e+w>=0)
				up-=e,up+=(e+w);
				else if(e<0)
				down+=-w;
			}
			if(r!=n){
				int e=ask(r+1)-ask(r);
				if(e<0&&e-w>=0){
					down-=-e,up+=e-w;
				}
				else if(e<0&&e-w<0) down-=-e,down+=-(e-w); 
				else if(e>=0) up-=e,up+=e-w;
			}
		}
		ans=max(suan(up),suan(down));
		cout<<ans<<endl;
		add(l,r,w);
	}
}

Searchlights 2000

https://www.luogu.com.cn/problem/CF1408D
题解:我们可以维护上升x步后所需右移的最大步数f(x),易知图像必为阶梯状(若一灯处于另一灯的照明区域内则可去除),故下面的点需要右移的距离一定>=上面的点。我们首先可以确定两种解决方案,即一直向上或一直向前,若二者并非最优解,则一定是先走上再走右,而最优情况下一定有点上升到了与灯塔等高位置(因为需要其向右运动带出所有在其下面的点即所有未出去的点在此时有同样的右边界,而然高度越大显然可以使得目标更接近,其中一点到达灯塔高度即为某一右移长度下的临界条件,否则是答案一二之一)。那么我们可以枚举上升至各个灯塔高度时的最小右移距离,ans=max(fi)+x(i>=x).
代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e3+100;
const int M=1e6+100;
int ans,n,m,f[M],limit;
int a[N],b[N],c[N],d[N];
inline void ckmax(int &a,int b){
	a=a<b?b:a;//让 a 取到 a,b 间较大值 
}
inline void ckmin(int &a,int b){
	a=a>b?b:a;//让 a 取到 a,b 间较小值 
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&a[i],&b[i]);
	for(int i=1;i<=m;i++)
		scanf("%d%d",&c[i],&d[i]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if (d[j]<b[i]) continue;
			ckmax(limit,d[j]-b[i]);
			ckmax(f[d[j]-b[i]],c[j]-a[i]+1);
		}
	ans=limit+1;//只向右边走,走出边界 
	for(int i=limit,maxn=0;i>=0;i--){
		ckmax(maxn,f[i]);ckmin(ans,i+maxn);
	}
	printf("%d",ans);
	return 0;
}

Euclid's nightmare 2100

https://www.luogu.com.cn/problem/CF1466F
题解:由于1的个数只有1和2,对于2,容易想到是将i与j连边,使得任意联通块只有x-1条边,x个点(每个边代表一个向量,而若有多余边可以用其他边即环上另一条路径代替),对于只有1个1的点1,我们认为是将i与n+1相连,如此我们便可以得到A的大小与A中的元素,对于T我们容易用A推出:A中选择不同的边所形成的串一定不同,故T=ΣC(A,i)=2^(A).
代码:

#include<cmath>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#define int long long
#define reg register
using namespace std;
const int maxn=5e5+5;
const int mod=1e9+7;
inline int read()
{
    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;
}
int father[maxn];
int Find(int x)
{
	if(father[x]!=x)
	father[x]=Find(father[x]);
	return father[x];
}
int n,m;
int s[maxn];
int tot=0;
int siz[maxn];
int v[maxn];
signed main()
{
	v[0]=1;
	n=read(),m=read();
	for(int i=1;i<=max(n,m)+5;i++)
	v[i]=v[i-1]*2%mod;
	for(reg int i=1;i<=m+1;i++)
		father[i]=i;
	int cnt=0;
	for(reg int i=1;i<=n;i++)
	{
		int k=read(),x,y;
		if(k==1)
			x=read(),y=m+1;
		else
			x=read(),y=read();
		int nowx=Find(x),nowy=Find(y);
		if(nowx==nowy)
		continue;
		father[nowx]=nowy;
		s[++tot]=i;
	}
	int ans=v[tot]%mod;
	printf("%lld %lld\n",ans,tot);
	for(reg int i=1;i<=tot;i++)
		printf("%lld ",s[i]);
	printf("\n");
 	return 0;
}

D. Weight the Tree 2000

https://codeforces.com/problemset/problem/1646/D
题解:显然对于任意两个连接的点不能同时为好点(n=2特判),对于坏点显然取1最优,为了最小化sum我们可以考虑树形dp,dp方程f[u][0]=∑min(f[v][0],f[v][1]),f[u][1]=∑f[v][0]+d[u].再根据结果重新遍历一遍树选择最优的染色即可。

标签:ch,int,练习,up,down,2000,codeforce,ans,include
From: https://www.cnblogs.com/wjhqwq/p/17213211.html

相关文章

  • Educational Codeforces Round 105 (Rated for Div
    EducationalCodeforcesRound105(RatedforDiv.2)ABCString给定一个字符串只有A、B和C构成。要求替换A、B、C为')'和'(',并且相同字母替换的是一样的,使得字符串变......
  • Codeforces Round 713 (Div
    CodeforcesRound713(Div.3)A-BPalindrome给定字符串只含有\('?'\'0'\'1'\),给定字符串中1的个数\(a\)和0的个数\(b\),你需要将?替换成0或1,使得该字符串变成回文......
  • Codeforces Round 857 (Div. 2)
    比赛地址做到F心态崩了,自然不会去做G.F考虑最终路径一定是这样的1到x节点在x处攒够路费再到n.后者可以通过从n跑dij来求最短路。考虑前者需要求从1~x的最小代价。......
  • CodeForces 1147F Zigzag Game
    洛谷传送门CF传送门很有意思的题。考虑若无边权的限制则B必胜,不妨猜想有了限制之后仍然是B必胜。假设A选了I(若A选了D可以边权取相反数),若B走了\((a,b)\)......
  • Java基础知识点(集合、ArrayList集合、基本数据类型对应的包装类及
    1.为什么要有集合?集合它可以自动扩容。2.集合存储数据类型的特点:不能直接存基本数据类型,需要将其变为包装类再存入,可以存引用数据类型。二:集合和数组的对比长度:数组的长度固......
  • 字符串函数练习
    字符串函数练习一:下列程序会打印什么#include<stdio.h>intmain(void){charnote[]="Seeyouatthesnackbar.";char*ptr;ptr=note;put......
  • Codeforces Round 857 (Div. 2)
    题目链接A核心思路读懂题目也就不难了。//Problem:A.Likes//Contest:Codeforces-CodeforcesRound857(Div.2)//URL:https://codeforces.com/contest/180......
  • Codeforces比赛规则梳理
    1、排名div选手们按Rating以1700为界划分为Div.1和Div.2两类,Div.1的比赛较难,Div.1的ABC三题会和Div.2的CDE三题相同。每次比赛结束后Rating都会依据此前各个选手的Rating和......
  • Codeforces Round #666 (Div. 2)D. Stoned Game(博弈问题)
    problemT和HL玩游戏,n堆石头,玩家轮流在石堆中选择一个(但不能是上一个人取的那堆)取一个石子一旦有一方不能取石头则判输solution统计所有石头数,如果总数小于mx(最多石头的一堆)......
  • 群论练习:证明 Polya 定理
    轨道-生成子引理设\(x\inX,\G_x=\{g:gx=x\},\O_x=Gx\)则\(|G|=|G_x||O_x|\)我们先证明\(G_x\)是\(G\)的一个子群,因为\(gx=x\tog^{-1}gx=gx......