Photoshop Layers

题意
有三个灯 R G B(默认初始为0 0 0)
对这个灯进行两种操作,一种是在现在的灯的基础上加上给出的数,并且和255取小
另一种则是将给出的数赋给R G B,这些数是以16进制的字符串给出的
题解
对于这个问题我们可以按一的多少对整个集合进行划分,对每一个划分进行前缀和操作,由于每一次的一都是赋值操作,所以只要查询范围内有一的存在,就可以直接输出r
如果没有一的存在,就可以用前缀和的思想r-(l-1)得到答案,由于下标在集合中一定是单调的,我们可以通过二分搜索得到离l最近的第一个1的位置;注意的是,l的值可能大于最后的一个1出现的位置,这个时候二分会越界,我们需要特殊判断;
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<iomanip>
using namespace std;
int t, n, q;
int sj(char a, char b) {
int x=0, y=0;
if (a >= '0' && a <= '9')x = (a - '0') * 16;
else if (a >= 'A' && a <= 'Z')x = (a - 'A' + 10) * 16;
if (b >= '0' && b <= '9')y = (b - '0');
else if (b >= 'A' && b <= 'Z')y = (b - 'A' + 10);
return x + y;
}
string s;
int x;
void solve() {
cin >> n >> q;
vector<int>stk;
vector<vector<int>>a(3, vector<int>(n+1));
for (int i = 1; i <= n; i++) {
cin >> x >> s;
if (x == 1) {
stk.emplace_back(i);
a[0][i] = sj(s[0], s[1]);
a[1][i] = sj(s[2], s[3]);
a[2][i] = sj(s[4], s[5]);
}
else {
a[0][i] += sj(s[0], s[1]) + a[0][i - 1];
a[1][i] += sj(s[2], s[3]) + a[1][i - 1];
a[2][i] += sj(s[4], s[5]) + a[2][i - 1];
}
}
while (q--) {
int l, r;
cin >> l >> r;
if (l > stk[stk.size() - 1]) {
cout << hex << uppercase << setw(2) << setfill('0') << min(a[0][r] - a[0][l - 1], 255) << setw(2) << setfill('0') << min(a[1][r] - a[1][l - 1], 255) << setw(2) << setfill('0') << min(a[2][r] - a[2][l - 1], 255) << endl;
}
else {
int u = lower_bound(stk.begin(), stk.end(), l) - stk.begin();
if (stk[u] <= r ) {
cout << hex << uppercase << setw(2) << setfill('0') << min(a[0][r], 255) << setw(2) << setfill('0') << min(a[1][r], 255) << setw(2) << setfill('0') << min(a[2][r], 255) << endl;
}
else {
cout << hex << uppercase << setw(2) << setfill('0') << min(a[0][r] - a[0][l - 1], 255) << setw(2) << setfill('0') << min(a[1][r] - a[1][l - 1], 255) << setw(2) << setfill('0') << min(a[2][r] - a[2][l - 1], 255) << endl;
}
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin.exceptions(ios::badbit | ios::failbit);
cin >> t;
while(t--)solve();
}
Game on Plane

题意
给出了n条直线,Alice可以选择1到n条直线,Bob需要画一条线,与Alice选的线的交点就是对Bob的惩罚值,Bob想要惩罚最少而Alice想要惩罚最多;
解题方法
由于Alice想要惩罚最多,所以Alice会选择斜率尽可能不同的点,而Bob会选择画一条与Alice选择直线中平行线最多的那组线的平行线;
所以Alice应该选择尽可能不平行的边 我们就可以将线按照斜率记录下来,统计到一个数组中,然后找出不平行的组,Alice一定会一组一组的选并且选择下一组时会将上一组选完;
这里由于斜率可能会出现小数,导致结果不准确,所以我们用(x,y)来表示它的斜率(学到了)
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<iomanip>
#include<map>
#include<memory.h>
using namespace std;
int t, n;
const int N = 100010;
pair<int, int>a[N];
int f[N];
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
void solve() {
cin >> n;
int x11, y11, x22, y22;
for (int i = 1; i <= n; i++) {
cin >> x11 >> y11 >> x22 >> y22;
if (x11 == x22)a[i] = { 0,1 };
else if (y11 == y22)a[i] = { 1,0 };
else {
int dx = x22 - x11, dy = y22 - y11;
if (dx < 0)dx = -dx, dy = -dy;
int d = gcd( abs(dx), abs(dy));
dx /= d,dy /= d;
a[i] = { dx,dy };
}
}
sort(a + 1, a + n + 1);//便于统计同斜率的有多少;
memset(f, 0, n + 10);
int i, j;
for (i = 1; i <= n; i=j) {
for (j = i; j <= n && a[i] == a[j]; j++);
for (int k = 1; k <= j - i; k++)f[k]++;
}
for (i = j = 1; i <= n; i++) {
if (f[j]==0)j++;
f[j]--;
cout << (i - j) << endl;
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin.exceptions(ios::badbit | ios::failbit);
cin >> t;
while(t--)solve();
}
Rise in Price(待补)

看了标程还是没有搞懂(先放标程待补)
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
typedef vector<P>V;
const int N=105;
int Case,n,m,i,j,k,a[N][N],b[N][N];ll ans;V f[N][N];P pool[1000005];
inline void ext(const P&t){
while(m&&pool[m].second<=t.second)m--;
if(!m||pool[m].first<t.first)pool[++m]=t;
}
inline void merge(const V&A,const V&B,V&C){
int ca=A.size(),cb=B.size(),i=0,j=0;
m=0;
while(i<ca&&j<cb)ext(A[i].first<B[j].first?A[i++]:B[j++]);
while(i<ca)ext(A[i++]);
while(j<cb)ext(B[j++]);
C.resize(m);
for(i=0;i<m;i++)C[i]=pool[i+1];
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
for(i=1;i<=n;i++)for(j=1;j<=n;j++)scanf("%d",&a[i][j]);
for(i=1;i<=n;i++)for(j=1;j<=n;j++)scanf("%d",&b[i][j]);
f[1][1].resize(1);
f[1][1][0]=P(a[1][1],b[1][1]);
for(i=1;i<=n;i++)for(j=1;j<=n;j++){
if(i==1&&j==1)continue;
if(i==1)f[i][j]=f[i][j-1];
else if(j==1)f[i][j]=f[i-1][j];
else merge(f[i-1][j],f[i][j-1],f[i][j]);
for(k=0;k<f[i][j].size();k++){
f[i][j][k].first+=a[i][j];
f[i][j][k].second+=b[i][j];
}
}
ans=0;
for(i=0;i<f[n][n].size();i++)ans=max(ans,1LL*f[n][n][i].first*f[n][n][i].second);
printf("%lld\n",ans);
}
}
1万+



被折叠的 条评论
为什么被折叠?



