Cubes-Codeforces-180E

Cubes:

我们先将每个正方形的光路投影找出来(在y轴上的截距所构成的区间)

然后,我们再考虑按照光线射到的先后顺序加入每个方格。

再用线段树统计这个投影区间内的最小高度的光线。这样我们就能够算出每个点被照亮的高度。

复杂度O(n2logn+).

注意:

在计算区间的时候选择前闭后开区间,这是因为我们要满足两个条件,

1.只通过一个点的光线不算照亮

2.假设先后修改(2,3),(1,2),(4,5)那么现在的(2,3)区间不能是(1,2)或(4,5)中间的一个.

代码很丑,凑合着看吧.(数据似乎没有和坐标轴平行的光,我就没管了.....)

  1 #include<cstdlib>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<map>
  7 using namespace std;
  8 const int maxn = 510, maxs = maxn * maxn * 5,inf = 0x3f3f3f3f;
  9 const int dx[] = {0,0,0,1,1},
 10        dy[] = {0,0,1,0,1};
 11 int ct;
 12 struct SEG{
 13     int sg[maxs * 3],tag[maxs * 3];
 14     void down(int x){
 15         if(tag[x]){
 16             sg[x << 1] = max(sg[x << 1], tag[x]);
 17             sg[x << 1|1] = max(sg[x << 1|1], tag[x]);
 18             tag[x << 1] = max(tag[x << 1], tag[x]);
 19             tag[x <<1|1] = max(tag[x << 1|1], tag[x]);
 20             tag[x] = 0;
 21         }
 22     }
 23     int qer(int x,int l,int r,int nl,int nr){
 24         down(x);
 25         if(l == nl && nr == r) return sg[x];
 26         int mid = (nl + nr) >> 1;
 27         if(r <= mid) return qer(x << 1, l, r, nl, mid);
 28         else if(l > mid) return qer(x << 1|1, l, r, mid + 1, nr);
 29         else{
 30             int t1 = qer(x << 1, l, mid, nl, mid);
 31             int t2 = qer(x << 1|1, mid + 1, r, mid+1, nr);
 32             return min(t1,t2);
 33         }
 34     }
 35     void mod(int x,int l,int r,int nl,int nr,int val){
 36         down(x);
 37         if(l == nl && nr == r){
 38             sg[x] = max(sg[x],val), tag[x] = max(tag[x],val);
 39             return;
 40         }
 41         int mid = (nl + nr) >> 1;
 42         if(r <= mid){
 43             mod(x << 1, l, r, nl, mid, val);
 44         }
 45         else if(l > mid){
 46             mod(x << 1|1, l, r, mid + 1, nr, val);
 47         }
 48         else{
 49             mod(x << 1, l, mid, nl, mid, val);
 50             mod(x << 1|1, mid + 1, r, mid + 1, nr, val);
 51         }
 52         sg[x] = min(sg[x << 1], sg[x << 1|1]);
 53     }
 54
 55 }seg;
 56 int n,vx,vy;
 57 int tot;
 58 struct grid{
 59     int x,y;
 60     long long height;
 61 }g[maxn * maxn + 100];
 62 int cmp(grid x, grid y){
 63     if(x.x != y.x) return x.x > y.x;
 64     return x.y > y.y;
 65 }
 66 void trans(){
 67     if(vx > 0){
 68         vx = -vx;
 69         for(int i = 1; i <= tot; ++i) g[i].x = n - g[i].x - 1;
 70     }
 71     if(vy > 0){
 72         vy = -vy;
 73         for(int i = 1; i <= tot; ++i) g[i].y = n - g[i].y - 1;
 74     }
 75     if(vx == 0 && vy != 0){
 76         swap(vx,vy);
 77         for(int i = 1; i <= tot; ++i){
 78             swap(g[i].x, g[i].y);
 79             g[i].y = n - g[i].y - 1;
 80         }
 81     }
 82 }
 83 struct I{
 84     long long it;
 85     int rank;
 86 }data[maxn][maxn];
 87 map<long long, int>v;
 88 map<long long, int>::iterator itr;
 89 void inter(int x,int y){
 90     long long t = ((long double) y - vy * x / (long double)vx) * (long long)1e9;
 91     data[x][y] = (I){t,0};
 92     v[t] = 0;
 93 }
 94 void calc(){
 95     for(int i = 0; i <= n; ++i)
 96         for(int j = 0; j <= n; ++j)
 97             inter(i,j);
 98     for(itr = v.begin(); itr != v.end(); ++itr)
 99         itr->second = ++ct;
100     for(int i = 0; i <= n; ++i)
101         for(int j = 0; j <= n; ++j){
102             data[i][j].rank = v[data[i][j].it];
103         }
104 }
105 long long ans;
106 void ins(){
107     sort(g + 1, g + tot + 1, cmp);
108     for(int i = 1; i <= tot; ++i){
109         int up = -inf, down = inf;
110         for(int j = 1; j <= 4; ++j){
111             int tx = g[i].x + dx[j], ty = g[i].y + dy[j];
112             up = max(up, data[tx][ty].rank);
113             down = min(down, data[tx][ty].rank);
114         }
115         int r = up - 1, l = down;
116         if(l <= r && up >= 0){
117             int t = seg.qer(1, l , r, 1, ct);
118             ans += max(g[i].height - t, 0LL);
119             seg.mod(1, l, r, 1, ct, g[i].height);
120         }
121     }
122 }
123 void spj(){
124     long long ans = 0;
125     sort(g + 1, g + tot + 1, cmp);
126     for(int i = 1; i <= tot; ++i){
127         int x = g[i].x, y = g[i].y;
128         data[x][y].it = max(data[x][y].it, data[x+1][y].it);
129         ans += max(g[i].height - data[x][y].it, 0LL);
130         data[x][y].it = max(data[x][y].it, g[i].height);
131     }
132     cout << ans;
133 }
134 int main()
135 {
136     freopen("cubes.in","r",stdin);
137     freopen("cubes.out","w",stdout);
138     ios::sync_with_stdio(false);
139     cin >> n >> vx >> vy;
140     for(int i = 1; i <= n; ++i)
141         for(int j = 1; j <= n; ++j){
142             int t; cin >> t;
143             g[++tot] = (grid){i-1,j-1,t};
144         }
145     trans();
146     calc();
147     ins();
148     cout << ans;
149     return 0;
150 }

时间: 2024-10-12 17:13:16

Cubes-Codeforces-180E的相关文章

Anya and Cubes CodeForces - 525E (双端搜索)

大意: 给定$n$元素序列$a$, 可以任选不超过$k$个$a_i$变换为$a_i!$, 求变换后任选若干元素和为S的方案数. 分成两块暴搜, 复杂度$O(3^{\frac{n}{2}})$ #include <iostream> #include <algorithm> #include <cstdio> #include <unordered_map> #define REP(i,a,n) for(int i=a;i<=n;++i) using n

codeforces 525 E Anya and Cubes 中途相遇法

codeforces 525 E Anya and Cubes 中途相遇法 题意: 给出n个数a1,a2,...,an,要求从中选出一些数,可以把其中最多k个变成它自己的阶乘,然后选出的数求和,问最后和等于s的选法有多少种. 限制: 1 <= n <= 25; 0 <= k <= n; 1<= s <= 1e16; 1 <= ai <= 1e9 思路: 一般数据量20~30都会考虑中途相遇法,就是折半暴力. ps:用三进制暴力会比直接深搜多一个常数10,因为

Codeforces Round #116 (Div. 2, ACM-ICPC Rules) E. Cubes (尺取)

题目链接:http://codeforces.com/problemset/problem/180/E 给你n个数,每个数代表一种颜色,给你1到m的m种颜色.最多可以删k个数,问你最长连续相同颜色的序列的长度是多少. 将相同颜色的下标存到对应颜色的容器中,比如ans[a[i]].push_back(i)就是将下标为i颜色为a[i]的数存到ans[a[i]]容器中. 对于每种颜色序列,尺取一下 在差距小于k的情况下取能取到的最大长度. 1 //#pragma comment(linker, "/S

Codeforces Round #297 (Div. 2) E题. Anya and Cubes (中途相遇法)

题目地址:Anya and Cubes 比赛的时候居然没想起中途相遇法...这题也是属于想起来就很简单系列. 中途相遇法也叫折半搜索.就是处理前一半,把结果储存起来,再处理后一半,然后匹配前一半存储的结果. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib

Codeforces Round #297 (Div. 2)E. Anya and Cubes

题目链接:http://codeforces.com/problemset/problem/525/E 题意: 给定n个数,k个感叹号,常数S 下面给出这n个数. 目标: 任意给其中一些数变成阶乘,至多变k个. 再任意取一些数,使得这些数和恰好为S 问有多少方法. 思路: 三进制状压,0代表不取,1代表取阶乘,2代表直接取: 中途查找,节约空间: 代码如下: #include<cstdio> #include<cstring> #include<iostream> #i

Codeforces 679B - Bear and Tower of Cubes

679B - Bear and Tower of Cubes 题目大意:一个数x定义一种拆分方式,每次拆分取最大的a 且 a^3<=x,x减去a^3,之后重复同样的操作,直到 x变为0.给你一个数m( m<=1e15 ),让你取一个数q<=m,q能执行的操作数在小于等于m的数里面最大,且在操作数 最大的里面,值是最大的. 感觉这种思维题就是特别难.... 思路:设a为当前小于等于m的最大立方数.则对于当前的 m 我们有两种情况要考虑,第一种是res1=m-a^3 第二种是不想减去a^3,

CodeForces - 764B Timofey and cubes(模拟)

Young Timofey has a birthday today! He got kit of n cubes as a birthday present from his parents. Every cube has a number ai, which is written on it. Timofey put all the cubes in a row and went to unpack other presents. In this time, Timofey's elder

Codeforces Round #116 (Div. 2, ACM-ICPC Rules)---E. Cubes

Let's imagine that you're playing the following simple computer game. The screen displays n lined-up cubes. Each cube is painted one of m colors. You are allowed to delete not more than k cubes (that do not necessarily go one after another). After th

CodeForces 887B Cubes for Masha (暴力 || DFS)

Absent-minded Masha got set of n cubes for her birthday. At each of 6 faces of each cube, there is exactly one digit from 0 to 9. Masha became interested what is the largest natural x such she can make using her new cubes all integers from 1 to x. To

CodeForces 520D Cubes

题意: 二维平面内有一个图形由n(10^5)个标有0~n-1的方块组成  保证它是稳定的  即每个方块要么落在地面上  要么下面(边或点相交)有至少一个方块支撑  现在两个人轮流拆这个图形  要求拆的过程中图形仍稳定  拆下的方块上的数字会形成一个n进制的数  先手想让这个数最大  后手想最小  问最后这个数字是几 思路: 简单的贪心思路  在不毁坏稳定性的前提下  先手拿大数字  后手拿小数字  程序写的暴力会n^2造成TLE 那么我们维护一个有序队列(set维护)  这里面装着可以拆的数字