A. Creating a Character
分析 : 注意有的情况c==0或c全部给b是可以的
code :
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll min(ll a,ll b){return a<b?a:b;}
ll max(ll a,ll b){return a>b?a:b;}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		ll a,b,c;
		cin>>a>>b>>c;
		if(a+c<=b) {
			cout<<"0\n"; continue;
		}
		ll tmp=b+c-a;
		if(tmp<0) cout<<max(c+1,1)<<"\n";
		else cout<<max(c-tmp/2,(ll)0)<<"\n";
	}
	return 0;
}
B. Zmei Gorynich
分析 :略
code :
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 104;
ll min(ll a,ll b){return a<b?a:b;}
ll max(ll a,ll b){return a>b?a:b;}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,flag=0; ll u,v,x,maxv=0,p=0,ans=0;
		scanf("%d%I64d",&n,&x);
		for(int i=1;i<=n;i++) {
			scanf("%I64d%I64d",&u,&v);
			if(u>=x) flag=1;
			maxv=max(maxv,u-v);
			p=max(p,u);
		}
		if(flag) printf("1\n");
		else if(maxv<=0) printf("-1\n");
		else {
			ll num=(x-p)/maxv,ans=0;
			x-=num*maxv;
			ans+=num;
			if(x>p) ans+=2;
			else ans++; 
			printf("%I64d\n",ans);
		}
	}
	return 0;
}
C. The Number Of Good Substrings
分析 :    s[ l ] == 1 的区间最长取长度为18的,如果区间更长,则肯定大于 |s| ,  但是需要加上有前导0的情况。
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 3;
int p[maxn];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		char s[maxn];
		scanf("%s",s+1);
		int n=strlen(s+1),sum,ans=0;
		for(int i=1;i<=n;i++) 
			if(s[i]=='0') p[i]=p[i-1]+1;
			else p[i]=p[i-1];
		for(int len=1;len<=18;len++) for(int i=1;i<=n-len+1;i++)
			if(s[i]=='1') {
				sum=0;
				for(int j=0;j<len;j++) 
					sum=(sum<<1)+s[i+j]-'0';
				if(sum>=len&&i-(sum-len)-1>=0&&sum-len==p[i-1]-p[i-(sum-len)-1]) ans++; 
			}
		printf("%d\n",ans);
	}
	return 0;
}
D. Coloring Edges
分析 : 发现无环的时候k=1,有环的时候k=2,有环时可令E(u->v,u>v) 为一种颜色,E(u->v , u<v) 为另一种颜色,即可保证没有同色环。那么重点在于判断是否有环存在,按照拓扑排序遍历即可(见代码)
code :
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5004;
vector<int> p[maxn];
int deg[maxn],a[maxn],b[maxn];
bool top_sort(int n)
{
	queue<int> q;
	int cnt=0;
	for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
	while(!q.empty()) 
	{
		int x=q.front(),y; 
		cnt++; q.pop();
		for(int i=0;i<p[x].size();i++) {
			y=p[x][i];
			deg[y]--;
			if(!deg[y]) q.push(y);
		}
	}
	return cnt==n;
}
int main()
{
	int m,n;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++) {
		scanf("%d%d",&a[i],&b[i]);
		p[a[i]].push_back(b[i]);
		deg[b[i]]++;
	}
	if(top_sort(n)) {
		printf("1\n");
		for(int i=1;i<=m;i++) printf("1 ");
	}
	else 
	{
		printf("2\n");
		for(int i=1;i<=m;i++) 
			if(a[i]>b[i]) printf("1 ");
			else printf("2 ");
	}
	return 0;
}
E. Sum Queries?
分析 :只需要两个某一位同时不为0的数即可,所以题目转化为求两个数满足某一位都不为0的和最小为多少,建立线段树维护每一位上不为0的数中最小值和次小值。这题代码实现对编程技巧要求较高(参考了某位神犇的博客),代码值得反复玩味
code :
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 2e9 + 1;
const int maxn = 2e5 + 3;
int a[maxn];
struct SegmentTree {
	int l,r,minv[10],mn[10];
}t[maxn<<2]; 
void pushup(int p)
{
	for(int i=0;i<10;i++) {
		t[p].minv[i]=min(t[p*2].minv[i],t[p*2+1].minv[i]);
		t[p].mn[i]=min(t[p*2].mn[i],t[p*2+1].mn[i]);
		t[p].mn[i]=min(t[p].mn[i],max(t[p*2].minv[i],t[p*2+1].minv[i]));
	}
}
void build(int p,int l,int r)
{
	t[p].l=l,t[p].r=r;
	for(int i=0;i<10;i++) t[p].minv[i]=t[p].mn[i]=INF;
	if(l==r) {
		for(int x=a[l],now=0;x;x/=10,now++)
			if(x%10) t[p].minv[now]=a[l];
		return; 
	}
	int mid=(l+r)>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	pushup(p);
}
void update(int p,int k,int x)
{
	if(t[p].l==t[p].r) {
		for(int i=0;i<10;i++) t[p].minv[i]=t[p].mn[i]=INF;
		for(int y=x,now=0;y;y/=10,now++) 
			if(y%10) t[p].minv[now]=x;
		return;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(mid>=k) update(p*2,k,x);
	else update(p*2+1,k,x);
	pushup(p);
}
pair<int,int> getmin(int p,int l,int r,int id)
{
	if(t[p].l==l&&t[p].r==r) return make_pair(t[p].minv[id],t[p].mn[id]);
	int mid=(t[p].l+t[p].r)>>1;
	if(mid<l) return getmin(p*2+1,l,r,id);
	else if(mid>=r) return getmin(p*2,l,r,id);
	else {
		pair<int,int> a=getmin(p*2,l,mid,id),b=getmin(p*2+1,mid+1,r,id);
		return make_pair(min(a.first,b.first),min(min(a.second,b.second),max(a.first,b.first)));
	}
}
int main()
{
	int n,q;
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	build(1,1,n);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1) {
			int k,x;
			scanf("%d%d",&k,&x);
			update(1,k,x);
		}
		else {
			int l,r,ans=INF;
			pair<int,int> tmp;
			scanf("%d%d",&l,&r); 
			for(int i=0;i<10;i++) {
				tmp=getmin(1,l,r,i);
				if(tmp.first!=INF&&tmp.second!=INF) ans=min(ans,tmp.first+tmp.second);
			}
			if(ans==INF) printf("-1\n");
			else printf("%d\n",ans);
		}
	}
	return 0;
}