codeforces round 321 div2 题解

A:最长上升子串 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define Fast_IO ios_base::sync_with_stdio(0);cin.tie(0)
int n;
int a[100100];
int main()
{
	cin>>n;
	int res = 1;
	int t = 1;
	scanf("%d", &a[1]);
	rep(i, 2, n){
		scanf("%d", &a[i]);
		if(a[i] >= a[i-1]) t++;
		else t = 1;
		res = max(t, res);
	}	
	cout<<res<<endl;
	return 0;
}

B: 排序后二分。或者排序后尺取。 因为排序后就是单调的了

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define Fast_IO ios_base::sync_with_stdio(0);cin.tie(0)
int n, d;
PII a[100100];
int minn[100100];
int maxn[100100];
ll sum[100100];
const int INF = 0x3f3f3f3f;
int main()
{
	cin>>n>>d;
	rep(i, 1, n){
		int x,y;
		scanf("%d %d", &x, &y);
		a[i].fi = x; a[i].se = y;
	}
	sort(a+1, a+n+1);
	ll res = -1;
	for(int i=1; i<=n; i++){
		sum[i] = sum[i-1] + a[i].se;
	}
	for(int i=1; i<=n; i++){
		int tmp = lower_bound(a+i, a+n+1, mp(d+a[i].fi, -1)) - a - 1;
		res = max(sum[tmp] - sum[i-1], res);
	}
	cout<<res<<endl;
	return 0;
}

C:水dfs  求有多少条能到达子节点的路径且中间连续的猫不超过k个。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define Fast_IO ios_base::sync_with_stdio(0);cin.tie(0)
int n,m;
vector<int> v[100100];
int a[100100];
int ans = 0;
void dfs(int u, int pre, int d){
	bool is = true;
	int size = v[u].size();
	for(int i=0; i<size; i++){
		int tmp = d;
		int to = v[u][i];
		if(to == pre) continue;
		is = false;
		if(a[to] == 0) tmp = 0;
		else if(tmp + 1 > m) continue;
		else tmp++;
		dfs(to, u, tmp);
	}
	if(is) ans++;
}
int main()
{
	cin>>n>>m;
	rep(i, 1, n) scanf("%d", &a[i]);
	rep(i, 1, n-1){
		int x,y;
		scanf("%d %d", &x, &y);
		v[x].pb(y);
		v[y].pb(x);
	}
	dfs(1, -1, a[1]);
	cout<<ans<<endl;
	return 0;
}

D:状压dp 和tsp问题基本一样

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define Fast_IO ios_base::sync_with_stdio(0);cin.tie(0)
int n,m,k;
int a[100];
ll dp[300000][20];
ll res = 0;
struct node{
	int to,w,next;
}edge[4000];
int tot;
int head[400];
void init(){
	tot = 0; memset(head, -1, sizeof(head));
}
void add_edge(int u, int v, int w){
	edge[tot].to = v;
	edge[tot].w = w;
	edge[tot].next = head[u];
	head[u] = tot++;
}
bool check(int s){
	int tmp = 0;
	while(s){
		if(s&1) tmp++;
		s>>=1;
	}
	return tmp==m;
}
bool g[20][20] = {false};
int main(){
	cin>>n>>m>>k;
	init();
	rep(i, 0, n-1)scanf("%d", a+i);	
	rep(i, 1, k){
		int x,y,z;
		scanf("%d %d %d", &x, &y, &z);
		x--, y--;
		add_edge(x, y, z);
		g[x][y] = true;
	}
	rep(i, 0, n-1)
		rep(j, 0, n-1){
			if(i == j) continue;
			if(g[i][j] == false)
				add_edge(i, j, 0);  
		}
	int sum = (1<<n);
	for(int i=0; i<n;i++)
		dp[1<<i][i] = a[i];
	for(int i=1; i<sum; i++){
		for(int j=0; j<n; j++){
			if((i&(1<<j)) == 0) continue;
			for(int k=head[j]; ~k; k=edge[k].next){
				int v = edge[k].to;
				int w = edge[k].w;
				if(i&(1<<v))continue;
				dp[i|(1<<v)][v] = max(dp[i][j] + w + a[v], dp[i|(1<<v)][v]);
			}
		}
	}
	for(int i=1; i<sum; i++){
		if(check(i))
		for(int j=0; j<n; j++){
			if(i&(1<<j))
				res = max(res, dp[i][j]);
		}
	}
	cout<<res<<endl;
	return 0;
}

E:线段树+hash。 为了不被卡 写了双hash,传说中的多项式hash大法

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define Fast_IO ios_base::sync_with_stdio(0);cin.tie(0)
int n,m,k;
const int mod2 = 1000000009;
const int MAXN = 100100;
const int seed = 13;
ll p[MAXN+10];
ll p2[MAXN +10];
ll sum[MAXN+10];
ll sum2[MAXN+10];
char a[MAXN+10];
void init(){
	p[0] = 1;
	sum[0] = 1;
	p2[0] = 1;
	sum2[0] = 1;
	for(int i=1; i<MAXN; i++){
		p[i] = p[i-1]*seed%mod;
		sum[i] = (sum[i-1]+p[i]) % mod;
		p2[i] = p2[i-1]*seed%mod2;
		sum2[i] = (sum2[i-1]+p2[i])%mod2;
	}
}
struct node{
	int l, r;
	int len;
	long long val;
	long long val2;
	int lazy;
}tree[MAXN*4];
void push_up(int i){
	tree[i].val = (tree[i<<1].val*p[tree[i<<1|1].len]%mod + tree[i<<1|1].val)%mod;
	tree[i].val2 = (tree[i<<1].val2*p2[tree[i<<1|1].len]%mod2 + tree[i<<1|1].val2)%mod2;
}
void push_down(int i){
	if(tree[i].lazy != -1){
		tree[i<<1].val =  sum[tree[i<<1].len-1] * tree[i].lazy % mod;
		tree[i<<1|1].val = sum[tree[i<<1|1].len-1] * tree[i].lazy % mod;
		tree[i<<1].val2 =  sum2[tree[i<<1].len-1] * tree[i].lazy % mod2;
		tree[i<<1|1].val2 = sum2[tree[i<<1|1].len-1] * tree[i].lazy % mod2;
		tree[i<<1].lazy = tree[i].lazy;
		tree[i<<1|1].lazy = tree[i].lazy;
		tree[i].lazy = -1;
	}
}
void build(int i, int l, int r){
	tree[i].l = l;
	tree[i].r = r;
	tree[i].len = r - l + 1;
	tree[i].lazy = -1;
	if(l == r){
		tree[i].val = a[l] - '0';
		tree[i].val2 = a[l] - '0';
		return;
	}
	int mid = (l+r)>>1;
	build(i<<1, l, mid);
	build(i<<1|1, mid+1, r);
	push_up(i);
}
void update(int i, int l, int r, int val){
	if(tree[i].l == l&&tree[i].r == r){
		tree[i].val = val*sum[tree[i].len-1]%mod;
		tree[i].val2 = val*sum2[tree[i].len-1]%mod2;
		tree[i].lazy = val;
		return;
	}
	push_down(i);
	int mid = (tree[i].l + tree[i].r)>>1;
	if(l > mid) update(i<<1|1, l, r, val);
	else if(r <= mid) update(i<<1, l, r, val);
	else{
		update(i<<1, l, mid, val);
		update(i<<1|1, mid+1, r, val);
	}
	push_up(i);
}
pair<long long, long long> query(int i, int l, int r){
	if(tree[i].l == l && tree[i].r == r){
		return mp(tree[i].val, tree[i].val2);
	}
	push_down(i);
	int mid = (tree[i].l + tree[i].r)>>1;
	if(l > mid) return query(i<<1|1, l, r);
	else if(r <= mid) return query(i<<1, l, r);
	else{
		pair<long long, long long> a =query(i<<1, l, mid);
		pair<long long, long long> b =query(i<<1|1, mid+1, r);
		long long t1 = (a.fi*p[r - (mid+1) + 1]%mod + b.fi)%mod;
		long long t2 = (a.se*p2[r - (mid+1) + 1]%mod2 + b.se)%mod2;
		return mp(t1, t2);	
	}
}
int main()
{
	init();
	cin>>n>>m>>k;
	scanf("%s", a+1);
	int q = m+k;
	build(1, 1, n);
	while(q--){
		int cmd, x, y, z;
		scanf("%d %d %d %d", &cmd, &x, &y, &z);
		if(cmd == 2) {
			if(y-x+1 == z) {puts("YES"); continue;};
			pair<long long, long long> a = query(1, x, y-z);
			pair<long long, long long> b = query(1, x+z, y);
			if(a.fi == b.fi && a.se == b.se) printf("YES\n");
			else printf("NO\n");
		}	
		else
			update(1, x, y, z);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值