codeforces 1257
https://www.luogu.com.cn/problem/CF1257F
简单来说就是:给你 n 个数 a[ 1 ] ~ a[ n ], n <= 100; 让你找一个 x ,使得每个元素异或x后的每个新元素上的二进位上的1的个数一样。
思路:每个元素最多30个位置,可以想到的就是我们枚举这个x,因为元素个数也就100个;
所以最简单粗暴的方法就是枚举出这个x然后与每个元素进行异或,将异或结果保存下来,全都一样就是解了;
但是我们知道对于这种暴力枚举,我们都可以想到一些小优化,折半枚举。所以我们将x的30个位置拆成两半,cnt【0】【1】,表示这个x异或第一个元素后,后15位置有1的个数,cnt【1】【1】,表示这个x异或第一个元素后,前15个位置有1的个数;
所以我们需要求出来的就是cnt【0】【1】+cnt【1】【1】=cnt【0】【2】+cnt【1】【2】=.......;
-(+cnt【1】【2】-cnt【1】【1】)=cnt【0】【2】-cnt【0】【1】
所以就是我们先将所由左侧的求i出来后存进map,再让枚举右侧的时候查询map里面有没有记录过的,有就直接得出答案。
#include <bits/stdc++.h> #define LL long long #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f3f3f3f #define mem(i, j) memset(i, j, sizeof(i)) #define pb push_back using namespace std; int ans = -1, n; map < vector< int >, int > mp; vector< int > Q; int a[105]; void dfs1(int num, int statu){ if(num > 15) { Q.clear(); for(int i = 1; i <= n; i++) { Q.push_back(__builtin_popcount((statu ^ a[i]) % (1 << 15))); } for(int i = 1; i < n; i++) { Q[i - 1] = Q[i] - Q[i - 1]; } Q.pop_back(); if(!mp[Q]) mp[Q] = statu; return ; } dfs1(num + 1, statu); dfs1(num + 1, statu | (1 << (num - 1))); } void dfs2(int num, int statu) { if(num > 15) { Q.clear(); for(int i = 1; i <= n; i++){ ///__builtin_popcount(x) 用于计算x的二进制位上1的个数。 Q.push_back(__builtin_popcount(statu ^ (a[i] >> 15))); } for(int i = 1; i < n; i++) { Q[i - 1] = -1 * (Q[i] - Q[i - 1]); } Q.pop_back(); /// 弹出最后一个元素。 if(mp[Q]) { ans = mp[Q] | (statu << 15); } return ; } dfs2(num + 1, statu); dfs2(num + 1, statu | (1 << (num - 1))); } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); } dfs1(1, 0); dfs2(1, 0); printf("%d\n", ans); return 0; }
E
https://www.luogu.com.cn/problemnew/solution/CF1257E
例如
1~i cnt1[n]-cnt1[i]
i+1~j cnt2[i]+cnt2[n]-cnt2[j];
j+1~n cnt3[j]
#include <bits/stdc++.h> #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define ll long long #define LL long long using namespace std; const int maxn = (ll) 2e5 + 5; const int mod = 1000000007; const int inf = 0x3f3f3f3f; int cnt1[maxn], cnt2[maxn], cnt3[maxn]; int minn[maxn]; vector<int> v1, v2, v3; int main() { start; int k1, k2, k3; cin >> k1 >> k2 >> k3; v1.resize(k1 + 5); v2.resize(k2 + 5); v3.resize(k3 + 5); /*输入并标记*/ for (int i = 1; i <= k1; ++i) { cin >> v1[i]; ++cnt1[v1[i]]; } for (int i = 1; i <= k2; ++i) { cin >> v2[i]; ++cnt2[v2[i]]; } for (int i = 1; i <= k3; ++i) { cin >> v3[i]; ++cnt3[v3[i]]; } int n = k1 + k2 + k3; for (int i = 1; i <= n; ++i) {//前缀和 cnt1[i] = cnt1[i - 1] + cnt1[i]; cnt2[i] = cnt2[i - 1] + cnt2[i]; cnt3[i] = cnt3[i - 1] + cnt3[i]; } /*如分析*/ for (int i = 0; i <= n; ++i) minn[i] = cnt3[i] - cnt2[i]; for (int i = n - 1; i >= 0; --i) minn[i] = min(minn[i + 1], minn[i]); int ans = inf; for (int i = 0; i <= n; ++i) { int t = cnt2[i] - cnt1[i] + minn[i] + cnt1[n] + cnt2[n]; ans = min(ans, t); } cout << ans; return 0; }
D
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+10; int n,m,a[maxn],suf[maxn],b[maxn],p[maxn],s[maxn]; int main() { int t;scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=1;i<=n;i++) b[i]=-1; for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%d %d",&p[i],&s[i]),b[s[i]]=max(b[s[i]],p[i]); suf[n+1]=-1; for(int i=n;i>=1;i--) suf[i]=max(suf[i+1],b[i]); int pos=1,ans=0; while(pos<=n) { int cur=pos; int maxx=a[pos]; while(cur<=n && suf[cur-pos+1]>=maxx) { cur++; maxx=max(maxx,a[cur]); } if(cur==pos) {ans=-1;break;} ans++; pos=cur; } printf("%d\n",ans); } }