zoukankan      html  css  js  c++  java
  • CF1430

    CF1430

    那个博客搭好遥遥无期。

    A:

    看代码。

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    	int t;scanf("%d",&t);
    	while(t--)
    	{
    		int n;scanf("%d",&n);
    		if(n % 3 == 0)
    		{
    			printf("%d 0 0
    ",n / 3);
    		}
    		if(n % 3 == 1)
    		{
    			if(n < 7)puts("-1");
    			else printf("%d 0 1
    ",(n - 7) / 3);
    		}
    		if(n % 3 == 2)
    		{
    			if(n < 5)puts("-1");
    			else printf("%d 1 0
    ",(n - 5) / 3);
    		}
    	}
    	return 0;
    }
    

    B:

    显然把最大的几个都倒到一起最优。

    #include<bits/stdc++.h>
    using namespace std;
    int n,k;
    #define MAXN 200010
    int a[MAXN];
    void work()
    {
    	scanf("%d%d",&n,&k);
    	for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
    	sort(a + 1,a + 1 + n);
    	long long sum = 0;
    	for(int i = n,p = 1;i >= 1 && p <= k + 1;--i,++p)sum += a[i];
    	printf("%lld
    ",sum);
    	return;
    }
    int main()
    {
    	int testcases;
    	scanf("%d",&testcases);
    	while(testcases--)work();
    	return 0;
    }
    

    C:

    最后一定削成 (2) ,按照样例的提示做就行了。

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    void work()
    {
    	scanf("%d",&n);
    	printf("2
    ");
    	if(n == 2)
    	{
    		printf("1 2
    ");
    		return;
    	}
    	printf("%d %d
    ",n,n - 2);
    	printf("%d %d
    ",n - 1,n - 1);
    	for(int i = n - 3;i >= 1;--i)printf("%d %d
    ",i,i + 2);
    	return;
    }
    int main()
    {
    	int testcases;scanf("%d",&testcases);
    	while(testcases--)work();
    	return 0;
    }
    

    D:

    我们肯定是先找靠前的长度大于 (1) 的段删。

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    #define MAXN 200010
    int a[MAXN];
    int getc()
    {
    	char c = getchar();
    	while(!isdigit(c))c = getchar();
    	return c - '0';
    }
    struct seg{int v,l,p;}s[MAXN];
    bool operator < (seg a,seg b){return a.p < b.p;}
    int sn = 0;
    set<seg> ss,sl;
    void work()
    {
    	scanf("%d",&n);
    	for(int i = 1;i <= n;++i)a[i] = getc();
    	sn = 0;
    	for(int i = 1;i <= n;++i)
    	{
    		if(i != 1 && a[i] == a[i - 1])++s[sn].l;
    		else s[++sn] = (seg){a[i],1,i};
    	}
    	int ans = 0;
    	ss.clear();sl.clear();
    	for(int i = 1;i <= sn;++i)ss.insert(s[i]);
    	for(int i = 1;i <= sn;++i)if(s[i].l > 1)sl.insert(s[i]);
    	while(!ss.empty())
    	{
    		++ans;
    		if(!sl.empty())
    		{
    			set<seg>::iterator it = sl.begin();
    			seg t = *it;sl.erase(it);
    			ss.erase(ss.find(t));
    			--t.l;
    			if(t.l > 1)sl.insert(t);
    			ss.insert(t);
    		}
    		else
    		{
    			set<seg>::iterator it = ss.begin();
    			ss.erase(*it);
    		}
    		if(!ss.empty())
    		{
    			set<seg>::iterator it = ss.begin();
    			seg t = *it;
    			ss.erase(*it);
    			if(t.l > 1)sl.erase(*it);
    		}
    	}
    	printf("%d
    ",ans);
    	return;
    }
    int main()
    {
    	int testcases;
    	scanf("%d",&testcases);
    	while(testcases--)work();
    	return 0;
    }
    

    E:

    一定是一个一个一次移到最终位置最优,于是用树状数组统计前面还有多少个。

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    #define MAXN 200010
    char a[MAXN],r[MAXN];
    char getc()
    {
    	char c = getchar();
    	while(!islower(c))c = getchar();
    	return c;
    }
    deque<int> s[26];
    int c[MAXN];
    int lowbit(int x){return x & (-x);}
    void add(int p,int x){for(int i = p;i <= n;i += lowbit(i))c[i] += x;return;}
    int query(int p){int res = 0;for(int i = p;i >= 1;i -= lowbit(i))res += c[i];return res;}
    int main()
    {
    	scanf("%d",&n);
    	for(int i = 1;i <= n;++i)a[i] = getc();
    	for(int i = 1;i <= n;++i)s[a[i] - 'a'].push_back(i);
    	for(int i = 1;i <= n;++i)r[i] = a[n - i + 1];
    	for(int i = 1;i <= n;++i)add(i,1);
    	long long ans = 0;
    	for(int i = 1;i <= n;++i)
    	{
    		int pos = s[r[i] - 'a'].front();s[r[i] - 'a'].pop_front();
    		int fr = query(pos);
    		add(pos,-1);
    		ans += fr - 1;
    	}
    	cout << ans << endl;
    	return 0;
    }
    

    F:

    好神啊,看了别人代码才会,直接做不好做,因为如果 (r_i<l_{i+1}) 那么每次可以直接丢掉,但是如果 (r_i=l_{i+1}) ,那么就不能在之间丢掉,就很不好处理,但是可以倒着做,这样就可以记录每次是不是一定会给上一轮剩下什么,就可以判断是否可行了。求最小值只要在保证能给下一次剩下足够的东西的前提下尽量不扔。因为只要能完成,这次能扔下次也能扔,所以尽量不扔一定优。不存在这次扔了能让下次少扔的情况,因为这样已经是能留下的最多的了。

    #include<bits/stdc++.h>
    using namespace std;
    int n,k;
    #define MAXN 2010
    int l[MAXN],r[MAXN],a[MAXN];
    long long rem[MAXN];
    int main()
    {
    	scanf("%d%d",&n,&k);
    	for(int i = 1;i <= n;++i)scanf("%d%d%d",&l[i],&r[i],&a[i]);
    	long long need = 0;
    	for(int i = n;i >= 1;--i)
    	{
    		need = a[i];
    		if(r[i] == l[i + 1])need += rem[i + 1];
    		if(need > 1ll * (r[i] - l[i] + 1) * k)
    		{
    			puts("-1");
    			return 0;
    		}
    		rem[i] = max(0ll,need - 1ll * (r[i] - l[i]) * k);
    	}
    	long long ans = 0,cur = 0;
    	for(int i = 1;i <= n;++i)
    	{
    		if(cur < rem[i])
    		{
    			ans += cur;
    			cur = k;
    		}
    		ans += a[i];
    		cur = (k - (a[i] - cur) % k) % k;
    	}
    	cout << ans << endl;
    	return 0;
    }
    

    G:

    先化式子:

    [sum_{i=1}^mw_i imes(a_{x_i}-a_{y_i})=sum_{i=1}^na_i imes (outs[i]-ins[i]) ]

    然后我们一定是一层一层 (DP) 的,刚开始写了个记录层数的 (DP)( ext{T}) ,之后发现可以每次给之前的都加 (sumv) 相当于是加了一层。

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    #define MAXN 20
    #define S 600000
    long long sums[S];
    long long f[S];
    long long val[MAXN];
    int ex[S];
    struct edge
    {
    	int to,nxt;
    }e[MAXN * MAXN];
    int edgenum = 0,lin[MAXN];
    void add(int a,int b)
    {
    	e[++edgenum] = (edge){b,lin[a]};lin[a] = edgenum;
    	return;
    }
    int pre[S];
    int res[MAXN];
    bool indep[S];
    int main()
    {//freopen("w.in","r",stdin);freopen("my.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	int a,b,v;
    	for(int i = 1;i <= m;++i)
    	{
    		scanf("%d%d%d",&a,&b,&v);
    		val[a] += v;val[b] -= v;
    		add(a,b);
    	}//for(int i = 1;i <= n;++i)cout << val[i] << " ";cout << endl;
    	int tot = (1 << n) - 1;
    	for(int s = 0;s <= tot;++s)
    	{
    		for(int k = 1;k <= n;++k)
    		{
    			if(!(s & (1 << (k - 1))))continue;
    			for(int i = lin[k];i != 0;i = e[i].nxt)ex[s] |= (1 << (e[i].to - 1));
    		}
    	}
    	for(int s = 0;s <= tot;++s)
    		for(int k = 1;k <= n;++k)
    			if(s & (1 << (k - 1)))sums[s] += val[k];
    	memset(f,0x3f,sizeof(f));
    	for(int s = 0;s <= tot;++s)
    	{
    		indep[s] = true;
    		for(int k = 1;k <= n && indep[s];++k)
    			if(s & (1 << (k - 1)))
    				for(int i = lin[k];i != 0 && indep[s];i = e[i].nxt)
    					if(s & (1 << (e[i].to - 1)))indep[s] = false;
    	}
    	for(int s = 0;s <= tot;++s)if(indep[s])f[s] = sums[s];
    	for(int s = 0;s <= tot;++s)
    	{
    		int expand = tot ^ s;
    		for(int k = expand;k != 0;k = (k - 1) & expand)
    		{
    			if(!indep[k])continue;
    			if(ex[k] & s)continue;
    			if(f[s] + sums[s | k] < f[s | k])
    			{
    				f[s | k] = f[s] + sums[s | k];
    				pre[s | k] = s;
    			}
    		}
    	}//for(int s = 0;s <= tot;++s)cout << s << " - " << pre[s] << " " << f[s] << endl;
    	for(int cur = tot,i = 1;cur != 0;cur = pre[cur],++i)
    	{
    		int lay = cur ^ pre[cur];
    		for(int k = 1;k <= n;++k)if(lay & (1 << (k - 1)))res[k] = i;
    	}
    	for(int i = 1;i <= n;++i)printf("%d ",res[i]);puts("");
    	return 0;
    }
    
  • 相关阅读:
    day 3 python 函数 -- lambda -- 内置函数 -- 进制转换
    day 2 基本类型和函数
    linux 的常用命令
    python & diretory 对象
    python & list对象
    python & str对象函数
    python全栈之路 1 python的基本介绍
    centos6.5 配置SSH
    js禁止高频率连续点击思路
    $.ajax参数备注-转转转
  • 原文地址:https://www.cnblogs.com/wjh15101051/p/13807788.html
Copyright © 2011-2022 走看看