https://codeforces.com/contest/1244/problem/C
求出满足以下公式的
给出n,p,w,dn,p,w,d,求解:
x⋅w+y⋅d=p
x+y≤n
首先是w>d的
接下来我们可以分析我们用暴力枚举来枚举一个然后来判断另一个对吧,但是呢纯暴力是妥妥tle
我们又知道w>d,那么y
因为如果
y=w,那么相当于w∗dw∗d,然后取了w个d,那么不如取d个w更优。
#includeusing namespace std; #define rep(i,a,b) for(ll i=(a);i<=(b);++i) #define dep(i,a,b) for(ll i=(a);i>=(b);--i) #define pb push_back typedef long long ll; const int maxn=(int)2e5+100; const int mod=(int)1e9+7; ll n,p,d,w; int main(){ scanf("%lld%lld%lld%lld",&n,&p,&w,&d); if(n*w n) return puts("-1"),0; return printf("%lld %lld %lld",x,y,n-x-y),0; } if(i*d>p) break; } return puts("-1"),0; }
https://codeforces.com/contest/1244/problem/D
给出三行数据,第一行表示选择颜色1的各个顶点的花费,第二行表示颜色2...
然后每三个相邻点颜色不能一样
容易发现只有链的情况合法,链的情况就很简单了。
因为颜色个数较少,所以直接枚举颜色排列染色就行。
#includeusing namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define dep(i,a,b) for(int i=(a);i>=(b);--i) #define pb push_back typedef long long ll; const int maxn=(int)2e5+100; const int mod=(int)1e9+7; int n,ind[maxn],pos=1,pp=1,id[10][maxn]; ll c[4][maxn]; vector g[maxn<<1]; ll dfs(int pos,int st,int fa,int col1,int col2){ ll ans=0;int col; rep(i,1,3) if(i!=col1&&i!=col2) col=i; id[pos][st]=col; if((int)g[st].size()==1) return c[col-1][st]; rep(i,0,1) if(g[st][i]!=fa) return c[col-1][st]+dfs(pos,g[st][i],st,col2,col); } int main(){ scanf("%d",&n); rep(i,1,n) scanf("%lld",&c[0][i]); rep(i,1,n) scanf("%lld",&c[1][i]); rep(i,1,n) scanf("%lld",&c[2][i]); rep(i,1,n-1){ int u,v;scanf("%d%d",&u,&v); g[u].pb(v);g[v].pb(u); ind[u]++;ind[v]++; } int num=0,st=0,ed=0; rep(i,1,n){ if(ind[i]==1){ num++; if(st) ed=i; else st=i; } else if(ind[i]>2) return puts("-1"),0; } if(num!=2) return puts("-1"),0; ll ans=(ll)1e18; int st2=g[st][0],st3; rep(i,0,1) if(g[st2][i]!=st) st3=g[st2][i]; rep(i,1,3) rep(j,1,3) if(i!=j){ pos++; id[pos][st]=i;id[pos][st2]=j; ll tmp=c[i-1][st]+c[j-1][st2]+dfs(pos,st3,st2,i,j); if(ans>tmp) ans=tmp,pp=pos; } printf("%lld\n",ans); rep(i,1,n) printf("%d ",id[pp][i]); puts(""); }
https://codeforces.com/contest/1244/problem/E
- 题意: 一个序列,每次可以选一个数+1或-1,可以操作k次,求最小化最大减最小的差.
- 思路: 因为差值是有单调性的(如果差值d在序列里可以在变化操作k内实现,那么我们可以花费更多操作次数缩小d继续查找,如果不能说明d太小k次操作不够支撑,那我们可以增大d继续查找),所以二分差,肯定有一个a[i]是不变的(肯定的嘛使差值最小你锁定两个数字其中一个不用变,变另外一个就行了),check时就枚举a[i]不变(上界下界枚举两次),然后lower_bound找到比下界小的,要加到下界,upper_bound找到比上界大的,要减到上界,算操作次数是否满足小于k.
#include#define MP make_pair #define fi first #define se second #define sz(x) (int)(x).size() #define all(x) (x).begin(), (x).end() // #define Local using namespace std; typedef long long ll; typedef pair pii; const int N = 1e5 + 5; ll n, k; int a[N]; ll sum[N]; bool chk(int d) { for(int i = 1; i <= n; i++) { int low = lower_bound(a + 1, a + n + 1, a[i]) - a - 1; int high = upper_bound(a + 1, a + n + 1, a[i] + d) - a; ll tot = 1ll * low * a[i] - sum[low] + sum[n] - sum[high - 1] - 1ll * (n - high + 1) * (a[i] + d); if(tot <= k) return true; } for(int i = 1; i <= n; i++) { int high = upper_bound(a + 1, a + n + 1, a[i]) - a; int low = lower_bound(a + 1, a + n + 1, a[i] - d) - a - 1; ll tot = 1ll * low * (a[i] - d) - sum[low] + sum[n] - sum[high - 1] - 1ll * (n - high + 1) * a[i]; if(tot <= k) return true; } return false; } void run() { int res=0; for(int i = 1; i <= n; i++) cin >> a[i]; sort(a + 1, a + n + 1); for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i]; int l = 0, r = 1e9 + 1, mid; while(l <=r) { mid = (l + r) >> 1; if(chk(mid)) res=mid,r=mid-1; else l= mid+1; } cout << res<< '\n'; } int main() { while(cin >> n >> k) run(); return 0; }
https://codeforces.com/contest/1244/problem/G
sum=∑i=max(pi,qi)≤k,sum要最大
最小的sum肯定是(n)*(n+1)/2;
考虑将第一个排列顺序排放。
然后考虑第二个排列刚开始也是顺序排放的。
然后考虑交换位置视为元素左移和元素右移。
显然,元素右移不会对答案产生影响。
但是元素左移,左移几个位置它就产生多少贡献。
那么显然可以发现这个变化是连续的,直接贪心即可。
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #include#define fi first #define se second #define endl "\n" using namespace std; using db = double; using ll = long long; using ull = unsigned long long; using pII = pair ; using pLL = pair ; constexpr int mod = 1e9 + 7; template inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } template inline void chmax(T1 &x, T2 y) { if (x < y) x = y; } template inline void chmin(T1 &x, T2 y) { if (x > y) x = y; } inline int rd() { int x; cin >> x; return x; } template inline void rd(T &x) { cin >> x; } template inline void rd(vector &vec) { for (auto &it : vec) cin >> it; } #define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) void err() { cout << "\033[39;0m" << endl; } template void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); } template class T, typename t, typename... A> void err(const T &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); } inline void pt() { cout << endl; } template void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); } template class T, typename t, typename... A> void pt(const T &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); } ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; } inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; } //head constexpr int N = 1e6 + 10; int n, a[N]; ll k; void run() { ll base = 1ll * n * (n + 1) / 2; if (base > k) return pt(-1); for (int i = 1; i <= n; ++i) a[i] = i; ll remind = k - 1ll * n * (n + 1) / 2; int low = 1; for (int i = n; i >= 1 && i > low; --i) { if (i - low <= remind) { remind -= i - low; swap(a[i], a[low]); ++low; } else { swap(a[i], a[i - remind]); remind = 0; break; } } pt(k - remind); for (int i = 1; i <= n; ++i) cout << i << " \n"[i == n]; for (int i = 1; i <= n; ++i) cout << a[i] << " \n"[i == n]; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cout << fixed << setprecision(20); while (cin >> n >> k) run(); return 0; }