HGOI 20200804

T1 排序(sort)

答案就是有逆序对的元素个数

因为可以把有逆序对的元素从大到小操作一遍就行

\(O(nlogn)\)

好像还有 \(O(n)\) 做法 orz

#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second

const int N = 5000010 ;

int n, ans ;
int bit[N], a[N], dp[N] ;

void mdf(int p, int v) {
	for (; p <= n; p += p & -p) bit[p] = max(bit[p], v) ;
}

int ask(int p) { 
	int ans = 0 ;
	for (; p; p -= p & -p) ans = max(ans, bit[p]) ;
	return ans ;
}

char Getchar() { 
	static char buf[100000], *S = buf, *T = buf ;
    if (S == T) {  
    	S = buf ;
        T = S + fread(buf, 1, 100000, stdin) ;
        if (S == T) return EOF ;  
    }  
    return *S++ ; 
}

int read() {
    int f = 1, x = 0 ;
    char ch = Getchar() ;
    while (!isdigit(ch)) { if (ch == '-') f = -1 ; ch = Getchar() ; }
    while (isdigit(ch)) { x = x * 10 + ch -'0' ; ch = Getchar() ; }
    return x * f ;
}

signed main() {
	freopen("sort.in", "r", stdin) ;
	freopen("sort.out", "w", stdout) ;
	n = read() ;
	rep(i, 1, n) a[i] = read() ;
	memset(bit, 0, sizeof(bit)) ;
	per(i, n, 1) {
		if (ask(a[i] - 1) == 1) {
	//		cout<<i<<endl;
			ans++ ;
		}
		mdf(a[i], 1) ;
	}
	printf("%d\n", ans) ;
	return 0 ;
}

T2 图(graph)

bitset

枚举 \(v\) 得到 \(u\) 的集合 \(U\)\(w\) 的集合 \(W\)

然后要求就是所有的 \((u,x)\)\(x\) 属于 \(W\)

使用 \(bitset\) 暴力

时间复杂度 \(O(n^3/64)\)

因为跑不满,实测很快,十几毫秒飞速过

#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second

const int N = 2030 ;

int n ;
char s[N] ;
bitset <N> tr[N], tb[N], w ;
vector <int> u, b[N], ib[N], r[N], ir[N] ;

bool solve(vector <int> R[N], vector <int> IR[N], bitset <N> T[N]) {
	rep(v, 1, n) {
	//	cout<<v<<endl;
//		if (!siz(ir[v]) || !siz(r[v])) continue ;
		u.clear() ;
		w.reset() ;
		rep(i, 0, siz(IR[v]) - 1) u.pb(IR[v][i]) ;
		rep(i, 0, siz(R[v]) - 1) w[R[v][i]] = 1 ;
		rep(i, 0, siz(u) - 1) {
		//	cout<<u[i]<<endl;
		//	rep(j, 1, 4) cout << T[u[i]][j] << " " ; cout << endl ;
		//	rep(j, 1, 4) cout << w[j] << " " ; cout << endl ;
			int U = u[i] ;
			bitset <N> tmp ; 
			tmp = T[U] | w ;
		//	rep(j, 1, 4) cout << tmp[j] << " " ; cout << endl ;
			if (tmp != T[U]) return false ;
		}
		//cout<<"ok\n";
	}
	return true ;
}

signed main() {
//	freopen("graph.in", "r", stdin) ;
//	freopen("graph.out", "w", stdout) ;
	int t ; scanf("%d", &t) ;
	while (t--) {	
		scanf("%d", &n) ;
		rep(i, 1, n) r[i].clear(), ir[i].clear(), b[i].clear(), ib[i].clear(), tr[i].reset(), tb[i].reset() ;
		rep(i, 1, n) {
			scanf("%s", s) ;
			rep(j, 1, n) 
			if (s[j - 1] != 'U') {
				if (s[j - 1] == 'R') r[i].pb(j), ir[j].pb(i), tr[i][j] = 1 ;
				else b[i].pb(j), ib[j].pb(i), tb[i][j] = 1 ;
			}
		}
		int ans = 1 ;
		ans &= solve(r, ir, tr) ;
		if (ans) ans &= solve(b, ib, tb) ; 
		puts(ans ? "T" : "N") ;
	}	

	return 0 ;
}

T3 或(or)

数位dp

这种东西NOIP是不可能考的(flag)

搬题解

\(f(i,j,k)\) 表示计算到第 \(i\) 位,当前 \(r\) 是否取到上界,\(l\) 是否取到上界 \((k)\) 的状态下的答案,\(g(i,j,k)\) 表示方案数

时间复杂度 \(O(len)\) 大概是 \(10^6\)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 1010000,mod = 1e9+7;

int f[N][2][2],g[N][2][2],c[N],len,n;
int add(int x,int y){x += y;if (x >= mod) x -= mod;return x;}
int cal(int,int,int);
int read(){
	int x = 0;char ch = getchar();
	while (ch < '0' || '9' < ch) ch = getchar();
	return ch - '0';
}
int main(){
	freopen("or.in","r",stdin);
	freopen("or.out","w",stdout);
	scanf("%d",&n);
	for (int i = n;i >= 1;i--) c[i] = read();
	len = n;
	memset(f,0,sizeof(f));
	memset(g,0,sizeof(g));
	f[len+1][1][1] = 0;
	g[len+1][1][1] = 1;
	for (int i = len;i >= 1;i--){
		for (int j = 0;j < 2;j++)
			for (int k = 0;k < 2;k++)
				if (g[i+1][j][k]){
					for (int a = 0;a < 2;a++)
						for (int b = 0;b < 2;b++){
							int u = cal(c[i],j,a),v = cal(a,k,b);
							if (u != -1 && v != -1){
								if (a|b) {
									f[i][u][v] = add(f[i][u][v],add(f[i+1][j][k],g[i+1][j][k]));
									g[i][u][v] = add(g[i][u][v],g[i+1][j][k]);
								}
								else{
									f[i][u][v] = add(f[i][u][v],f[i+1][j][k]);
									g[i][u][v] = add(g[i][u][v],g[i+1][j][k]);								
								}
							}
						}
				}
	}
	int ans = 0;
	for (int i = 0;i < 2;i++)
		for (int j = 0;j < 2;j++)
			ans = add(ans,f[1][i][j]);
	printf("%d\n",ans);
	return 0;
}
int cal(int x,int y,int z){
	if (y == 1 && z == x) return 1;
	if (y == 1 && z >  x) return -1;
	if (y == 1 && z <  x) return 0;
	if (y == 0) return 0; 
}
posted @ 2020-08-04 08:00  harryhqg  阅读(124)  评论(0编辑  收藏  举报