杭电多校总结2021-07-27

1004 Game on Plane

** Problem Description**
Alice and Bob are playing a game. In this game, there are n straight
lines on the 2D plane. Alice will select exactly k straight lines
l1,l2,…,lk among all the n straight lines first, then Bob will draw a
straight line L. The penalty of Bob is defined as the number of lines
in {l1,l2,…,lk} that shares at least one common point with L. Note
that two overlapping lines also share common points.

Alice wants to maximize the penalty of Bob while Bob wants to minimize
it. You will be given these n lines, please write a program to predict
the penalty of Bob for k=1,2,3,…,n if both of the players play
optimally.

Input
The first line contains a single integer T (1≤T≤500), the number of
test cases. For each test case:

The first line contains a single integer n (1≤n≤100000), denoting the
number of straight lines.

Each of the next n lines contains four integers xai,yai,xbi and ybi
(0≤xai,yai,xbi,ybi≤109), denoting a straight line passes both
(xai,yai) and (xbi,ybi). (xai,yai) will never be coincided with
(xbi,ybi).

It is guaranteed that the sum of all n is at most 1000000.

Output
For each test case, output n lines, the i-th (1≤i≤n) of which containing an integer, denoting the penalty of Bob when k=i.

大意:
两条直线存在公共点当且仅当它们重合或者它们斜率不同,因此Bob 的最优策略一定是避
开斜率出现次数最多的那些直线。Alice 为了让Bob 与尽量多的直线相交,最优策略就是最小
化斜率出现次数的最大值。
所以不断从每种斜率的直线中各选一种即可。

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

int t,n,xa,ya,xb,yb,dx,dy,i,j,k;
int f[100003];
pair<int,int> a[100003];
int gcd(int a,int b)
{
    if(b==0)return a;
    else gcd(b,a%b);
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
            dx=xa-xb;
            dy=ya-yb;
            if(dx==0)dy=1;
            else if(dy==0)dx=1;
            else
            {
                if(dx<0)
                {
                    dx=-dx;
                    dy=-dy;
                }
                int d=gcd(fabs(dx),fabs(dy));
                dx/=d;
                dy/=d;
            }
            a[i].first=dx;
            a[i].second=dy;
        }
        sort(a+1,a+n+1);
        for(int i=1;i<=n;++i)f[i]=0;//初始化记录斜率相同数量的组数
        for(int i=1;i<=n;i=j)
        {
            for(j=i;j<=n&&a[i]==a[j];++j);//j-i描述斜率相同直线数量
            for(int k=1;k<=j-i;++k)f[k]++;
        }
        for(int i=1,j=1;i<=n;++i)
        {
            while(f[j]==0)++j;
            --f[j];//--意味该线被选取
            printf("%d\n",i-j);//j来描述当前相同斜率最多的条数
        }
    }
    return 0;
}

1007 Photoshop Layers

** Problem Description**
Pixels in a digital picture can be represented with three integers
(R,G,B) in the range 0 to 255 that indicate the intensity of the red,
green, and blue colors. The color of a pixel can be expressed as a
six-digit hexadecimal capital string. For example, (R=100,G=255,B=50)
can be expressed as ‘‘64FF32’’.

There are n layers in Photoshop workstation, labeled by 1,2,…,n from
bottom to top. The screen will display these layers from bottom to
top. In this problem, you only need to handle the case that the color
of all the pixels in a layer are the same. The color of the i-th layer
is ci=(Ri,Gi,Bi), the blending mode of the i-th layer is mi
(mi∈{1,2}): If mi=1, the blending mode of this layer is ‘‘Normal’’.
Assume the previous color displayed on the screen is (Rp,Gp,Bp), now
the new color will be (Ri,Gi,Bi). If mi=2, the blending mode of this
layer is ‘‘Linear Dodge’’. Assume the previous color displayed on the
screen is (Rp,Gp,Bp), now the new color will be (min(Rp+Ri,255),
min(Gp+Gi,255), min(Bp+Bi,255)). You will be given q queries. In the
i-th query, you will be given two integers li and ri (1≤li≤ri≤n).
Please write a program to compute the final color displayed on the
screen if we only keep all the layers indexed within [li,ri] without
changing their order. Note that the color of the background is
(R=0,G=0,B=0).

Input
The first line contains a single integer T (1≤T≤10), the number of
test cases. For each test case:

The first line of the input contains two integers n and q
(1≤n,q≤100000), denoting the number of layers and the number of
queries.

In the next n lines, the i-th line contains an integer mi and a
six-digit hexadecimal capital string ci, describing the i-th layer.

In the next q lines, the i-th line contains two integers li and ri
(1≤li≤ri≤n), describing the i-th query.

Output
For each query, print a single line containing a six-digit hexadecimal capital string, denoting the final displayed color.

题意:有n次操作,操作有两种①操作一:使这次操作后的颜色都为当前RGB,②操作二:使当前的颜色RGB为上一次操作的颜色的RGB加上输入的RGB,超过255时为255,现在有q次询问,每次询问输入l,r,问一颜色RGB初始为(00,00,00)的背景通过l-r的操作后是什么颜色

解析:预处理出fi 表示图层i 左侧第一个合成方式为“普通” 的图层。对于每个询问,求出r 左
侧第一个合成方式为“普通” 的图层fr,则中间的部分都是“线性减淡”,可以用前缀和求出结
果,最后与255 取最小值。
时间复杂度O(n + q)。
8 Restore

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

const int N =2e5+100;

int arr[N][4];
int sum[N][4];

inline int min(int a,int b){return (a<b)?a:b;}

signed main(){
	int t;scanf("%d",&t);
	while(t--){
		int n,q;scanf("%d %d",&n,&q);
		for(int i=1,p;i<=n;i++){
			scanf("%d %X",&arr[i][0],&p);
			sum[i][3]=p%256;
			p>>=8;
			sum[i][2]=p%256;
			p>>=8;
			sum[i][1]=p;
			sum[i][0]=i;
			if(arr[i][0]==2){
				sum[i][0]=sum[i-1][0];
				sum[i][1]+=sum[i-1][1];
				sum[i][2]+=sum[i-1][2];
				sum[i][3]+=sum[i-1][3];
			}
		}
		while(q--){
			int l,r;scanf("%d %d",&l,&r);
			if(l>sum[r][0]) printf("%02X%02X%02X\n",min(sum[r][1]-sum[l-1][1],255),min(sum[r][2]-sum[l-1][2],255),min(sum[r][3]-sum[l-1][3],255));
			else printf("%02X%02X%02X\n",min(sum[r][1],255),min(sum[r][2],255),min(sum[r][3],255));
		}
	}
}

1011 Segment Tree with Pruning

** Problem Description**
Chenjb is struggling with data stucture now. He is trying to solve a
problem using segment tree. Chenjb is a freshman in programming
contest, and he wrote down the following C/C++ code and ran ‘‘Node*
root = build(1, n)’’ to build a standard segment tree on range [1,n]:

Node* build(long long l, long long r) {
Node* x = new(Node);
if (l == r) return x;
long long mid = (l + r) / 2;
x -> lchild = build(l, mid);
x -> rchild = build(mid + 1, r);
return x; }

Chenjb submitted his code, but unfortunately, got MLE (Memory Limit
Exceeded). Soon Chenjb realized that his program will new a large
quantity of nodes, and he decided to reduce the number of nodes by
pruning:

Node* build(long long l, long long r) {
Node* x = new(Node);
if (r - l + 1 <= k) return x;
long long mid = (l + r) / 2;
x -> lchild = build(l, mid);
x -> rchild = build(mid + 1, r);
return x; }

You know, Chenjb is a freshman, so he will try different values of k
to find the optimal one. You will be given the values of n and k,
please tell him the number of nodes that will be generated by his new
program.

Input
The first line contains a single integer T (1≤T≤10000), the number of
test cases. For each test case:

The only line contains two integers n and k (1≤k≤n≤1018), denoting a
query.

Output
For each query, print a single line containing an integer, denoting the number of segment tree nodes.

题意:
对区间[1,n]建线段树,返回条件是r−l+1<=k,问建成的线段树有多少节点?

记忆化搜索
线段树上代表区间长度相同的节点的子树点数相同,且最多只有O(log n) 种本质不同的区
间长度,对区间长度记忆化搜索即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
ll n,k;
map<ll,ll>T;
ll build(ll n)
{
    if(T.find(n)!=T.end()) return T[n];
    if(n<=k) return T[n]=1;
    else return T[n]=build(n/2)+build(n-n/2)+1;  
}
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        T.clear();
        cout<<build(n)<<endl;
    }return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值