[COCI2015-2016#4] ENDOR 题解
[COCI2015-2016#4] ENDOR 题解
首先要发现一个很重要的性质,那就是两只变色龙碰撞后回头,等效于两只变色龙继续往前走,其中向右走的颜色不变,而向左走的要改变颜色。
那这样就有一种
然后我们发现
我们考虑维护这个
#include<bits/stdc++.h> using namespace std; const int N = 1e5+100; int read() { int x = 0, f = 1; char ch = getchar(); while(ch<'0' || ch>'9') {if(ch == '-') f = -1; ch = getchar();} while(ch>='0'&&ch<='9') {x = x * 10 + (ch-48), ch = getchar();} return x * f; } struct xwx { int d, col, dir; bool operator < (const xwx &b) const { return d < b.d; } } a[N]; int n, K, L; int c[N]; double ans[50]; double w[50]; int sum; int dr[N], totr, cr[N];//记录向右走的变色龙的信息 void change(int del) { double b[50]; for(int i = 0; i<K; ++i) { b[(i+del)%K] = w[i]; } for(int i = 0; i<K; ++i) { w[i] = b[i]; } }//平移数组 int main() { n = read(), K = read(), L = read(); for(int i = 1; i<=n; ++i) { a[i].d = read(), a[i].col = read(); char op[3]; scanf("%s", op); if(op[0] == 'L') a[i].dir = 0; else a[i].dir = 1, ans[a[i].col]+=(L-a[i].d); } sort(a+1, a+n+1); for(int i = 1; i<=n; ++i) { c[i] = a[i].col; }//完全没有意义的一步( for(int i = 1; i<=n; ++i) { if(a[i].dir) { ++totr; dr[totr] = a[i].d; cr[totr] = a[i].col; sum = (sum + a[i].col)%K;//用来确定颜色最后会变成什么 if(totr > 1) { change(a[i].col); w[a[i].col]+=(0.5*(dr[totr] - dr[totr-1])); } continue; } // dr[totr+1] = a[i].d; // for(int j = totr; j>=1; --j) { // ans[c[i]]+=(0.5*(dr[j+1] - dr[j])); // c[i] = (c[i] + cr[j])%K; // } // ans[c[i]]+=0.5*(a[i].d + dr[1]);//n^2做法 for(int j = 0; j<K; ++j) { ans[(c[i]+j)%K]+=w[j]; } ans[c[i]]+=(0.5*(a[i].d - dr[totr]));//第一只遇到的向右走的变色龙 ans[(c[i] + sum)%K]+=(0.5*(a[i].d + dr[1]));//走过最后一只变色龙后还要一直走到终点。 } for(int i = 0; i<K; ++i) { printf("%.1lf\n", ans[i]); } return 0; }