ZR 2020普转提七连测day4

A

我们考虑序列的最后一个数字 (x),那么 (>x) 的数字在排名中就没有贡献了,所以我们只能让前面 (<x) 的数尽量靠前。贪心的想我们肯定让这个 (x) 尽量大,也就是说如果把越大的数放在后面,那么就会有更多小的数在前面。

于是答案等价于求反过来的最大字典序。

#include <bits/stdc++.h>

#define fi first
#define se second
#define db double
#define U unsigned
#define P std::pair<int,int>
#define LL long long
#define pb push_back
#define MP std::make_pair
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 1e5 +5;

std::vector<int> G[MAXN];
int deg[MAXN];
int n,m;

inline void Solve(){
	scanf("%d%d",&n,&m);
	FOR(i,1,n) G[i].clear();
	FOR(i,1,n) deg[i] = 0;
	FOR(i,1,m){
		int u,v;scanf("%d%d",&u,&v);
		G[v].pb(u);++deg[u];
	}
	std::priority_queue<int> q;
	FOR(i,1,n) if(!deg[i]) q.push(i); 
	std::vector<int> ans;
	while(!q.empty()){
		int v = q.top();q.pop();ans.pb(v);
		for(auto x:G[v]){
			if(!--deg[x]){
				q.push(x);
			}
		}
	}
	std::reverse(all(ans));
	if(ans.size() != n) puts("Impossible!");
	else{
		for(auto x:ans) printf("%d ",x);
		puts("");
	}
}

int main(){
	int T;scanf("%d",&T);
	while(T--) Solve();
	return 0;
}

B

暴力做法是枚举两位后在哈希表里查一下,复杂度 (O(nlog^2 a_i))

注意到我们可以分开枚举,枚举 (a) 的某一位,将对应的数插入到哈希表,然后枚举 (b) 的某一位查询,注意要减掉多算的,复杂度 (O(n log a_i))。注意这样会把 (a_i=b_i) 多算 (log a_i) 次,特判一下就行。

#include <bits/stdc++.h>

#define fi first
#define se second
#define db double
#define U unsigned
#define P std::pair<LL,LL>
#define LL long long
#define pb push_back
#define MP std::make_pair
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 1e5 + 5;
int n,m,a[MAXN],b[MAXN];
const int mod = 19260817;
std::mt19937 g(time(NULL));
int BASE;

inline char nc(){
    #define SIZE 1000000+3
    static char buf[SIZE],*p1 = buf+SIZE,*p2 = buf+SIZE;
    if(p1 == p2){
        p1 = buf;p2 = buf+fread(buf,1,SIZE,stdin);
        if(p1 == p2) return -1;
    }
    return *p1++;
    #undef SIZE
}

template <typename T>
inline void read(T &x){
    x = 0;int flag = 0;char ch = nc();
    while(!isdigit(ch)){
        if(ch == '-') flag = 1;
        ch = nc();
    }
    while(isdigit(ch)){
        x = (x<<1) + (x<<3) + (ch^'0');
        ch = nc();
    }
    if(flag) x = -x;
}

struct HASH{
	struct Edge{
		int val,cnt,nxt;
	}e[MAXN];
	int head[mod],cnt = 0;
	
	inline void insert(int x){
		x ^= BASE;
		int b = x%mod;
		for(int i = head[b];i;i = e[i].nxt){
			if(e[i].val == x){
				e[i].cnt++;
				return;
			}
		}
		e[++cnt] = (Edge){x,1,head[b]};head[b] = cnt;
	}
	
	inline int find(int x){
		x ^= BASE;
		int b = x%mod;
		for(int i = head[b];i;i = e[i].nxt){
			if(e[i].val == x) return e[i].cnt;
		}
		return 0;
	}
}S;

int main(){
	BASE = g()%((1<<30));
	read(n);read(m);
	FOR(i,1,n){
		int x;read(x);S.insert(x);
	}
	LL ans = 0;
	FOR(i,1,m){
		int x;read(x);
		FOR(a,0,29){
			FOR(b,a+1,29){
				ans += S.find(x^(1<<a)^(1<<b));
			}
		}
	}
	printf("%lld
",ans);
	return 0;
}

C

[post cid="1399" /]
这场CF的 E

#include <bits/stdc++.h>

#define fi first
#define se second
#define db double
#define U unsigned
#define P std::pair<int,int>
#define LL long long
#define pb push_back
#define MP std::make_pair
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 5e5 + 5;
const int ha = 1e9 + 7;
int k,n,m;
P a[2][MAXN];
std::vector<int> S;
int lim[2][MAXN];
int f[2][MAXN];
// 当前这一位是0/1 上一个不一样的在哪里 

inline void add(int &x,int y){
	x += y;if(x >= ha) x -= ha;
}

inline int qpow(int a,int n=ha-2){
	int res = 1;
	while(n){
		if(n & 1) res = 1ll*res*a%ha;
		a = 1ll*a*a%ha;
		n >>= 1;
	}
	return res;
}

int main(){
	scanf("%d%d%d",&k,&n,&m);
	S.pb(0);S.pb(k);
	FOR(i,1,n){
		scanf("%d%d",&a[0][i].fi,&a[0][i].se);--a[0][i].fi;
		S.pb(a[0][i].fi);S.pb(a[0][i].se);
	}
	FOR(i,1,m){
		scanf("%d%d",&a[1][i].fi,&a[1][i].se);--a[1][i].fi;
		S.pb(a[1][i].fi);S.pb(a[1][i].se);
	}
	CLR(lim,-1);
	std::sort(all(S));S.erase(std::unique(all(S)),S.end());
	FOR(i,1,n){
		a[0][i].fi = std::lower_bound(all(S),a[0][i].fi)-S.begin();
		a[0][i].se = std::lower_bound(all(S),a[0][i].se)-S.begin();
		lim[0][a[0][i].se] = std::max(lim[0][a[0][i].se],a[0][i].fi);
	}
	FOR(i,1,m){
		a[1][i].fi = std::lower_bound(all(S),a[1][i].fi)-S.begin();
		a[1][i].se = std::lower_bound(all(S),a[1][i].se)-S.begin();
		lim[1][a[1][i].se] = std::max(lim[1][a[1][i].se],a[1][i].fi);
	}
	int n = S.size();
	FOR(i,0,1) FOR(j,1,n) lim[i][j] = std::max(lim[i][j],lim[i][j-1]);
	f[0][0] = 1;int sm0 = 1,tp0 = 0,sm1 = 0,tp1 = 0;
	FOR(i,0,n-2){
		while(tp0 <= lim[1][i]) add(sm0,ha-f[0][tp0]),++tp0;
		while(tp1 <= lim[0][i]) add(sm1,ha-f[1][tp1]),++tp1;
		add(f[1][i],sm0);add(f[0][i],sm1);
		int gx = qpow(2,S[i+1]-S[i]-1);add(gx,ha-1);
		gx = 1ll*gx*(sm0+sm1)%ha;
		add(f[0][i+1],gx);add(f[1][i+1],gx);
		int t0 = sm0,t1 = sm1;
		add(sm0,t1);add(sm1,t0);
		add(sm0,gx);add(sm1,gx);
	}
	int ans = 0;
	FOR(i,0,n) if(i > lim[1][n]) add(ans,f[0][i]);
	FOR(i,0,n) if(i > lim[0][n]) add(ans,f[1][i]);
	printf("%d
",ans);
	return 0;
}

D

考虑这个条件等价于第 (i) 个位置可以有一个容量是 ([a_i,b_i]) 的物品,要求凑出 (p) 的最小代价。

于是单调队列优化 dp 即可。

#include <bits/stdc++.h>

#define fi first
#define se second
#define db double
#define U unsigned
#define P std::pair<int,int>
#define LL long long
#define pb push_back
#define MP std::make_pair
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 1000+5;
int n,a[MAXN],b[MAXN],c[MAXN],p;
LL f[2][10005];
int now;

inline void Solve(){
	scanf("%d%d",&n,&p);
	FOR(i,1,n) scanf("%d",a+i);
	FOR(i,1,n) scanf("%d",b+i);
	FOR(i,1,n) scanf("%d",c+i);
	now = 0;CLR(f[now],0x3f);
	f[now][0] = 0;
	FOR(i,1,n){
		CLR(f[now^1],0x3f);
		std::deque<int> q;
		FOR(j,0,p){
			if(j-a[i] >= 0){
				while(!q.empty() && f[now][q.back()] >= f[now][j-a[i]]) q.pop_back();
				q.pb(j-a[i]);
			}
			while(!q.empty() && q.front() < j-b[i]) q.pop_front();
			if(!q.empty()) f[now^1][j] = f[now][q.front()]+c[i];
			f[now^1][j] = std::min(f[now^1][j],f[now][j]);
		}
		now ^= 1;
	}
	f[now][p] > 2e9 ? puts("IMPOSSIBLE!!!") : printf("%lld
",f[now][p]);
}

int main(){
	int T;scanf("%d",&T);
	while(T--) Solve();
	return 0;
}
原文地址:https://www.cnblogs.com/rainair/p/14305498.html