ACM-ICPC國際大學生程式設計競賽北京賽區(2015)網路賽
補題。
列舉圓心點,然後二分半徑。注意圓的邊上不能有點。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<queue> #include<stack> #include<set> #include<map> #define LL long long #define MP make_pair #define xx first #define yy second #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1|1 #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; const double eps=1e-8; int sign(double x){ return (x>eps)-(x<-eps); } double sqr(double x){return x*x;} struct Point{ double x,y; void input(){ scanf("%lf%lf",&x,&y); } }p[111]; double dist(Point a,Point b){ return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); } int check(int n,int m,int idx,double R){ int cnt=0; for(int i=0;i<n;i++){ if(sign(dist(p[idx],p[i])-R)<0) cnt++; } return cnt; } int main(){ int T;scanf("%d",&T); while(T--){ int n,m;scanf("%d%d",&n,&m); for(int i=0;i<n;i++) p[i].input(); int mi=400000; for(int i=0;i<n;i++){ int L=0,R=40000,ans=-1; while(L<=R){ int mid=(L+R)>>1; int tmp=check(n,m,i,mid); if(tmp>=m){ if(tmp==m) ans=mid; R=mid-1; }else L=mid+1; } if(ans!=-1){ for(int j=0;j<n;j++){ if(sign(dist(p[i],p[j])-ans)==0) ans=-1; } } if(ans!=-1) mi=min(ans,mi); } if(mi==400000) printf("%d\n",-1); else printf("%d\n",mi); } }
B-Mission Impossible 6
模擬一下就好了,據說如果V的時候長度超多限制,就不用貼上。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<queue> #include<stack> #include<set> #include<map> #define LL long long #define MP make_pair #define xx first #define yy second #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1|1 #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 20000; char s[maxn]; char ans[maxn]; int m; int cnt; int pos = 0; string clipboard = ""; int copyStuts = 0;//nothing int copPosition = -1; int mode = 0;// insert void delet(){ int len = 0; if(copyStuts == 0) { if(pos == cnt) { return; } for(int i = pos; i < cnt - 1; i ++) { ans[i] = ans[i + 1]; } cnt --; }else { if(pos >= copPosition) { len = pos - copPosition; for(int i = copPosition; i + len < cnt; i ++) { ans[i] = ans[i + len]; } pos = copPosition; copyStuts = 0; copPosition = -1; cnt -= len; }else { len = copPosition - pos; for(int i = pos; i + len < cnt; i ++) { ans[i] = ans[i + len]; } copyStuts = 0; copPosition = -1; cnt -= len; } } } void backup() { if(pos == 0) return; pos --; for(int i = pos; i < cnt - 1; i ++) { ans[i] = ans[i + 1]; } cnt --; } void paste(){ int len = clipboard.size(); if(mode == 0) { if(cnt + len > m) return; for(int i = cnt - 1; i >= pos; i --) { ans[i + len] = ans[i]; } for(int i = 0; i < len; i ++) { ans[i + pos] = clipboard[i]; } pos = pos + len; cnt += len; }else{ if(pos + len > m) return; for(int i = 0; i < len; i ++) { ans[i + pos] = clipboard[i]; } pos = pos + len; cnt = max(cnt, pos); } } int main(){ int t; scanf("%d", &t); while(t --) { memset(ans, 0, sizeof ans); memset(s, 0, sizeof s); scanf("%d%s", &m, s); cnt = 0; pos = 0; clipboard = ""; copyStuts = 0;//nothing copPosition = -1; mode = 0;// insert for(int i = 0; s[i]; i ++) { if(s[i] == 'S') { copyStuts = 0; copPosition = -1; mode = 1 - mode; }else if(s[i] == 'L') { pos = max(0, pos - 1); }else if(s[i] == 'R') { pos = min(cnt, pos + 1); }else if(s[i] == 'D') { delet(); }else if(s[i] == 'B') { copyStuts = 0; copPosition = -1; backup(); }else if(s[i] == 'C') { if(copyStuts == 0) { copyStuts = 1; copPosition = pos; }else{ clipboard = ""; for(int i = min(copPosition, pos); i < max(copPosition, pos); i ++) { clipboard += ans[i]; } copyStuts = 0; copPosition = -1; } }else if(s[i] == 'V') { paste(); copyStuts = 0; copPosition = -1; }else{ copyStuts = 0; copPosition = -1; if(mode == 0) { if(cnt + 1 > m) continue; for(int i = cnt - 1; i >= pos; i --) { ans[i + 1] = ans[i]; } ans[pos] = s[i]; pos = pos + 1; cnt += 1; }else{ if(pos + 1 > m) continue; ans[pos] = s[i]; pos = pos + 1; cnt = max(cnt, pos); } } } if(cnt == 0) { puts("NOTHING"); continue; } for(int i = 0; i < cnt; i ++) { printf("%c", ans[i]); } puts(""); } return 0; }
C-Protecting Homeless Cats
佔坑。
很容易想到可以列舉x,然後就變成了n*2+1個在區間[x,x+m]中的數字異或為0的種數。裸的轉移是n^3的dp,但是可以用FWT加速複雜度變為mlogm。
學FWT可以去這裡NIM那道題。
E-Border Length//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<queue> #include<stack> #include<set> #include<map> #define LL long long #define MP make_pair #define xx first #define yy second #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1|1 #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; const int MOD = 1000000007; LL PowMod(LL a, LL n) { LL ret = 1; while(n) { if(n & 1) ret = ret * a % MOD; a = a * a % MOD; n >>= 1; } return ret; } LL a[1<<11]; LL Inv2 = PowMod(2, MOD - 2); void Transform(int l, int r, LL a[]) /// [l, r) { if(l == r - 1) return ; int len = (r - l) >> 1; int m = l + len; Transform(l, m, a); Transform(m, r, a); for(int i = l; i < m; i ++) { LL x1 = a[i], x2 = a[i + len]; a[i] = (x1 - x2 + MOD) % MOD; a[i + len] = (x1 + x2) % MOD; } } void ReTranform(int l, int r, LL a[]) { if(l == r - 1) return ; int len = (r - l) >> 1; int m = l + len; for(int i = l; i < m; i ++) { LL y1 = a[i], y2 = a[i + len]; a[i] = (y1 + y2) * Inv2 % MOD; a[i + len] = (y2 - y1 + MOD) * Inv2 % MOD; } ReTranform(l, m, a); ReTranform(m, r, a); } void Conv(LL a[], LL b[], int len) { Transform(0, len, a); Transform(0, len, b); for(int i = 0; i < len; i ++) a[i] = a[i] * b[i] % MOD; ReTranform(0, len, a); } int n, m, L, R; void solve() { LL ans = 0; for(int i = L; i <= R; i ++) { CLR(a, 0); for(int j = i; j <= i + m; j ++) a[j] = 1; Transform(0, 1 << 11, a); for(int j = 0; j < (1 << 11); j ++) { a[j] = PowMod(a[j], n * 2 + 1); } ReTranform(0, 1 << 11, a); ans += a[0]; ans %= MOD; } printf("%lld\n", ans); } int main() { while(scanf("%d%d%d%d", &n, &m, &L, &R) != EOF) { solve(); } return 0; }
這題其實就是一個水題,要求的是圓和普通多邊形相交的圖形的邊長。顯然可以先把多邊形所有線段在院內的求出來,然後再把圓弧在多邊形裡面的求出來就好了(據說圓被多邊形完全包圍的話,圓不算?)。第一個很容易求,第二個的話有兩種方法。
方法一:暴力,因為n只有1000所以可以求出所有線段和圓交點,然後以圓心做極角排序,然後暴力判斷每個弧是否在多邊形內就好了(用弧中點)。
方法二:對於多邊形的每條邊,兩個點和圓心構成一個三角形,判斷三角形和圓的相交情況,算出所有有向弧長,然後相加取絕對值就好了。詳情參見簡單多邊形和圓相交面積。
///n^2做法
#include<math.h>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const double eps=1e-8;
const double pi=acos(-1.0);
const int maxn=1111;
double sqr(double x) {
return x*x;
}
int sign(double x) {
return (x>eps)-(x<-eps);
}
struct Point {
double x,y;
Point(double _x=0,double _y=0) {
x=_x,y=_y;
}
Point operator+(const Point &a) {
return Point(x+a.x,y+a.y);
}
Point operator-(const Point &a) {
return Point(x-a.x,y-a.y);
}
Point operator*(const double &a) {
return Point(x*a,y*a);
}
Point operator/(const double &a) {
return Point(x/a,y/a);
}
double operator*(const Point &a) {
return x*a.y-y*a.x;
}
double operator^(const Point &a) {
return x*a.x+y*a.y;
}
double len() {
return sqrt(x*x+y*y);
}
void input() {
scanf("%lf%lf",&x,&y);
}
bool friend operator<(const Point &a,const Point &b) {
if(sign(a.x-b.x)==0) return a.y<b.y;
return a.x<b.x;
}
} p[maxn],cir;
struct Event {
Point tp;
double angle;
friend bool operator<(const Event &a,const Event &b) {
return a.angle<b.angle;
}
bool operator==(const Event &a) {
return sign(angle-a.angle)==0;
}
};
vector<Event> vec;
double R;
double mult(Point a,Point b,Point c) {
return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
double dist(Point a,Point b) {
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
double p_to_l(Point p,Point u,Point v) {
return fabs(mult(p,u,v))/dist(u,v);
}
bool pnt_on_seg(Point p,Point l1,Point l2){
return ((l1-p)^(l2-p))<eps;
}
int intersection_line_circle(Point p,Point v,Point cir,double R,vector<Point> &sol) {
double a=v.x,b=p.x-cir.x,c=v.y,d=p.y-cir.y;
double e=a*a+c*c,f=2*(a*b+c*d),g=b*b+d*d-R*R;
double delta=f*f-4*e*g;
if(sign(delta)<0) return 0;
double t1,t2;
Point p1,p2;
if(sign(delta)==0) {
t1=t2=-f/(2.0*e);
p1=p+v*t1;
sol.push_back(p1);
return 1;
}
t1=(-f-sqrt(delta))/(2.0*e);
p1=p+v*t1;
sol.push_back(p1);
t2=(-f+sqrt(delta))/(2.0*e);
p2=p+v*t2;
sol.push_back(p2);
return 2;
}
bool isin_circle(Point p,Point cir,double R) {
return sign(R-dist(p,cir))>0;
}
double calc(int n) {
double ret=0;
for(int i=0; i<n; i++) {
if(sign(p_to_l(cir,p[i],p[i+1])-R)>0) continue;
Point p1,p2;
vector<Point> v,vc;
vc.push_back(p[i]);
vc.push_back(p[i+1]);
int m=intersection_line_circle(p[i],p[i]-p[i+1],cir,R,v);
for(int j=0; j<m; j++) {
if(pnt_on_seg(v[j],p[i],p[i+1])) {
Event tmp;
tmp.tp=v[j];
double angle=atan2(v[j].y-cir.y,v[j].x-cir.x);
tmp.angle=angle;
vec.push_back(tmp);
vc.push_back(v[j]);
}
}
sort(vc.begin(),vc.end());
for(int j=0; j+1<vc.size(); j++) {
Point mid=(vc[j]+vc[j+1])*0.5;
if(isin_circle(mid,cir,R)) ret+=dist(vc[j],vc[j+1]);
}
}
return ret;
}
int inside(Point p[],int n,Point t){
int cnt=0;
for(int i=0;i<n;i++){
Point p1=p[i];
Point p2=p[(i+1)%n];
if(pnt_on_seg(t,p1,p2)&&sign((p1-t)*(p2-t))==0) return 2;
if(sign(p1.y-p2.y)==0) continue;
if(t.y<min(p1.y,p2.y)) continue;
if(sign(t.y-max(p1.y,p2.y))>=0) continue;
double x=(t.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
if(x>t.x) cnt++;
}
return cnt%2==1;
}
Point getMid(Event a,Event b,double R) {
double tmp=(a.angle+b.angle)*0.5;
return Point(cos(tmp),sin(tmp))*R;
}
double gao(int n) {
for(int i=0; i<=n; i++) p[i]=p[i]-cir;
for(int i=0; i<vec.size(); i++) {
vec[i].tp=vec[i].tp-cir;
}
Event tmp;
tmp.tp=Point(-R,0);
tmp.angle=pi;
vec.push_back(tmp);
tmp.tp=Point(-R,0);
tmp.angle=-pi;
vec.push_back(tmp);
cir=Point(0,0);
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
double ret=0;
int sz=vec.size();
for(int i=0; i+1<sz; i++) {
Point mid=getMid(vec[i],vec[i+1],R);
if(inside(p,n,mid)) ret+=fabs(vec[i+1].angle-vec[i].angle)*R;
}
return ret;
}
int main() {
int n;
while(scanf("%d",&n),n) {
for(int i=0; i<n; i++) p[i].input();
p[n]=p[0];
cir.input();
scanf("%lf",&R);
vec.clear();
double seg=calc(n);
double rad=gao(n);
printf("%.f\n",seg+rad);
}
}
///O(n)做法
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const double pi=acos(-1.0);
const double eps=1e-6;
double sqr(double x){return x*x;}
int sign(double x){
return (x>eps)-(x<-eps);
}
struct Point{
double x,y;
Point(double _x=0,double _y=0){
x=_x,y=_y;
}
Point operator+(const Point &a){
return Point(x+a.x,y+a.y);
}
Point operator-(const Point &a){
return Point(x-a.x,y-a.y);
}
double operator*(const Point &a){
return x*a.y-y*a.x;
}
double operator^(const Point &a){
return x*a.x+y*a.y;
}
Point operator*(const double &a){
return Point(x*a,y*a);
}
Point operator/(const double &a){
return Point(x/a,y/a);
}
double vlen(){
return sqrt(x*x+y*y);
}
void input(){
scanf("%lf%lf",&x,&y);
}
void output(){
printf("%f %f\n",x,y);
}
}p[2000],cir,res[2000];
double x_mult(Point sp, Point ep, Point op){
return (sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x);
}
double cross(Point a,Point b,Point c){
return (a.x-c.x)*(b.x-c.x)+(a.y-c.y)*(b.y-c.y);
}
double dist(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double cal_area(Point a,Point b,Point c,double r){
double A,B,C,x,y,tS;
A=dist(b,c);
B=dist(a,c);
C=dist(b,a);
int f;
if(sign(A-r)<0&&sign(B-r)<0){
return 0;
}else if(sign(A-r)<0&&sign(B-r)>=0){
x=(cross(a,c,b)+sqrt(r*r*C*C-x_mult(a,c,b)*x_mult(a,c,b)))/C;
tS=x_mult(a,b,c)/2;
return asin(tS*(1-x/C)*2/r/B)*r;
}else if(sign(A-r)>=0&&sign(B-r)<0){
y=(cross(b,c,a)+sqrt(r*r*C*C-x_mult(b,c,a)*x_mult(b,c,a)))/C;
tS=x_mult(a,b,c)/2;
return asin(tS*(1-y/C)*2/r/A)*r;
}else if(sign(fabs(x_mult(a,b,c))-r*C)>=0||sign(cross(b,c,a))<=0||sign(cross(a,c,b))<=0){
if(cross(a,b,c)<0)
if(x_mult(a,b,c)<0)
return (-acos(-1.0)-asin(x_mult(a,b,c)/A/B))*r;
else return (acos(-1.0)-asin(x_mult(a,b,c)/A/B))*r;
else return asin(x_mult(a,b,c)/A/B)*r;
}else{
x=(cross(a,c,b)+sqrt(r*r*C*C-x_mult(a,c,b)*x_mult(a,c,b)))/C;
y=(cross(b,c,a)+sqrt(r*r*C*C-x_mult(b,c,a)*x_mult(b,c,a)))/C;
tS=x_mult(a,b,c)/2;
return (asin(tS*(1-x/C)*2/r/B)+asin(tS*(1-y/C)*2/r/A))*r;
}
}
double solve(Point p[], int n, Point cir, double r){
double area=0;
for(int i=0;i<n;i++){
area+=cal_area(p[i], p[(i+1)%n], cir, r);
}
return area;
}
Point intersection(Point u1,Point u2,Point v1,Point v2){
double t=((u1-v1)*(v1-v2))/((u1-u2)*(v1-v2));
return u1+(u2-u1)*t;
}
bool pnt_on_seg(Point p,Point l1,Point l2){
return ((l1-p)^(l2-p))<eps;
}
void intersection_line_circle(Point c,double r,Point l1,Point l2,Point& p1,Point& p2){
Point p=c;
double t;
p.x+=l1.y-l2.y;p.y+=l2.x-l1.x;
p=intersection(p,c,l1,l2);
t=sqrt(r*r-dist(p,c)*dist(p,c))/dist(l1,l2);
p1=p+(l2-l1)*t;
p2=p-(l2-l1)*t;
}
double p_to_line(Point p,Point u,Point v){
return fabs((u-p)*(v-p))/dist(u,v);
}
int main(){
int n;
while(scanf("%d",&n),n){
for(int i=0;i<n;i++) p[i].input();
p[n]=p[0];
double r;
cir.input();scanf("%lf",&r);
double ans=0;
for(int i=0;i<n;i++){
double tmp=0;
if(sign(dist(p[i],cir)-r)<=0&&sign(dist(p[i+1],cir)-r)<=0){
tmp=dist(p[i+1],p[i]);
}else if(sign(p_to_line(cir,p[i],p[i+1])-r)<0){
Point p1,p2;
intersection_line_circle(cir,r,p[i],p[i+1],p1,p2);
if(pnt_on_seg(p1,p[i],p[i+1])&&pnt_on_seg(p2,p[i],p[i+1])){
tmp=dist(p1,p2);
}else if(pnt_on_seg(p1,p[i],p[i+1])&&!pnt_on_seg(p2,p[i],p[i+1])){
if(sign(dist(p[i],cir)-r)<=0) tmp=dist(p1,p[i]);
else tmp=dist(p[i+1],p1);
}else if(!pnt_on_seg(p1,p[i],p[i+1])&&pnt_on_seg(p2,p[i],p[i+1])){
if(sign(dist(p[i],cir)-r)<=0) tmp=dist(p2,p[i]);
else tmp=dist(p[i+1],p2);
}
}
ans+=tmp;
}
ans+=fabs(solve(p,n,cir,r));
printf("%.f\n",ans);
}
}
這題還是挺不錯的。首先對於第一顆樹,計算每個點的dfs序。那麼對於第二顆樹v節點說,第一顆樹中節點u和v的最近相交點,是u在樹1的祖先,和v在樹2的祖先。那麼,判斷v的祖先p是否是u的祖先,可以用p的dfs序的覆蓋區間(即p的子樹dfs序的區間)來判斷。顯然是求離v最近的祖先p,包括u點。這個可以在樹2上動態建一顆持久化線段樹來維護當前路徑中每個節點u最近是被哪個父親節點p覆蓋。由於要求的最近,所以每次更新的時候直接進行區間覆蓋就好了。
說的太爛,看程式碼吧。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
//#define lson l, m, rt << 1
//#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 100100;
const int maxm = maxn * 80;
vector<int> G1[maxn], G2[maxn];
int L[maxn], R[maxn], tot;
int seg[maxm], lson[maxm], rson[maxm];
int sz, T[maxn];
int dep1[maxn], dep2[maxn];
int n, m;
void dfs1(int u)
{
L[u] = tot ++;
for(int i = 0; i < G1[u].size(); i ++)
{
int v = G1[u][i];
dep1[v] = dep1[u] + 1;
dfs1(v);
}
R[u] = tot - 1;
}
int node()
{
lson[sz] = rson[sz] = -1;
seg[sz] = 0;
return sz ++;
}
int build(int l, int r)
{
int root = node();
seg[root] = 1;
return root;
}
void down(int rt)
{
if(seg[rt])
{
if(lson[rt] == -1)
lson[rt] = node();
seg[lson[rt]] = seg[rt];
if(rson[rt] == -1)
rson[rt] = node();
seg[rson[rt]] = seg[rt];
seg[rt] = 0;
}
}
int update(int rt, int u, int l, int r)
{
int root = node();
if(L[u] <= l && r <= R[u])
{
seg[root] = u;
return root;
}
int m = (l + r) >> 1;
down(rt);
if(L[u] <= m && R[u] > m)
{
lson[root] = update(lson[rt], u, l, m);
rson[root] = update(rson[rt], u, m + 1, r);
}
else if(L[u] <= m)
{
lson[root] = update(lson[rt], u, l, m);
rson[root] = rson[rt];
}
else
{
lson[root] = lson[rt];
rson[root] = update(rson[rt], u, m + 1, r);
}
return root;
}
int query(int rt, int q, int l, int r)
{
if(seg[rt]) return seg[rt];
int m = (l + r) >> 1;
if(q <= m) return query(lson[rt], q, l, m);
return query(rson[rt], q, m + 1, r);
}
void dfs2(int u, int fa)
{
for(int i = 0; i < G2[u].size(); i ++)
{
int v = G2[u][i];
dep2[v] = dep2[u] + 1;
T[v] = update(T[u], v, 1, n);
dfs2(v, u);
}
}
void solve()
{
tot = 1;
dep2[1] = dep1[1] = 0;
dfs1(1);
sz = 1;
T[1] = build(1, n);
dfs2(1, 0);
int ans = 0;
while(m --)
{
int u, v; scanf("%d%d", &u, &v);
u = (ans + u) % n + 1;
v = (ans + v) % n + 1;
ans = query(T[v], L[u], 1, n);
printf("%d %d %d\n", ans, dep1[u] - dep1[ans] + 1, dep2[v] - dep2[ans] + 1);
}
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF)
{
for(int i = 1; i <= n; i ++)
{
G1[i].clear(); G2[i].clear();
}
for(int i = 2; i <= n; i ++)
{
int v; scanf("%d", &v);
G1[v].push_back(i);
}
for(int i = 2; i <= n; i ++)
{
int v; scanf("%d", &v);
G2[v].push_back(i);
}
solve();
}
return 0;
}
G-Boxes
由於狀態數很少,所以直接預處理出所有答案就好了。狀態s表示的是,s的第i位表示i這個數在的位置。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 8 * 1e6;
int dp7[maxn];
int dp[7][666669];
int a[10], b[10];
void bfs(int n, int s, int dp[])
{
dp[s] = 0;
queue<int> Q;
Q.push(s);
while(!Q.empty())
{
int u = Q.front(); Q.pop();
int tmp = u;
for(int i = n; i >= 1; i --)
{
a[i] = tmp % 10;
tmp /= 10;
}
vector<int> vec[10];
for(int i = 1; i <= n; i ++)
{
vec[a[i]].push_back(i);
}
for(int i = 1; i <= n; i ++)
{
int sz = vec[i].size();
if(sz == 0) continue;
if(i != 1 && (vec[i - 1].size() == 0 || vec[i - 1][0] > vec[i][0]))
{
int v = 0;
for(int j = 1; j <= n; j ++)
{
if(j == vec[i][0])
v = v * 10 + i - 1;
else v = v * 10 + a[j];
}
if(dp[v] == -1)
{
dp[v] = dp[u] + 1;
Q.push(v);
}
}
if(i != n && (vec[i + 1].size() == 0 || vec[i + 1][0] > vec[i][0]))
{
int v = 0;
for(int j = 1; j <= n; j ++)
{
if(j == vec[i][0])
v = v * 10 + i + 1;
else v = v * 10 + a[j];
}
if(dp[v] == -1)
{
dp[v] = dp[u] + 1;
Q.push(v);
}
}
}
}
}
void init()
{
CLR(dp, -1); CLR(dp7, -1);
for(int i = 1; i <= 7; i ++)
{
int s = 0;
for(int j = 1; j <= i; j ++)
s = s * 10 + j;
if(i == 7) bfs(i, s, dp7);
else bfs(i, s, dp[i]);
}
}
int main()
{
init();
int T; scanf("%d", &T);
while(T --)
{
int n, m = 0;
scanf("%d", &n);
for(int i = 0; i < n; i ++)
{
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b, b + n);
for(int i = 0; i < n; i ++)
{
a[i] = lower_bound(b, b + n, a[i]) - b + 1;
}
for(int i = 0; i < n; i ++)
{
b[a[i]] = i + 1;
}
for(int i = 1; i <= n; i ++)
m = m * 10 + b[i];
if(n == 7) printf("%d\n", dp7[m]);
else printf("%d\n", dp[n][m]);
}
return 0;
}
H-Fractal
簽到題。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
double eps = 1e-10;
double k;
int sign(double x){
return (x>eps)-(x<-eps);
}
void solve()
{
int cnt = 1;
double L = 0.0, R = 0.5;
if(sign(R - k) == 0)
{
puts("1000");
return ;
}
if(sign(k) == 0)
{
puts("-1");
return ;
}
for(int i = 1; i <= 500; i ++)
{
double mid = (L + R) / 2;
if(sign(mid - k) == 0)
{
puts("-1");return ;
}
if(sign(mid - k) > 0)
{
printf("%d\n", cnt * 4);
return ;
}
L = mid; cnt ++;
}
puts("1000");
}
int main()
{
int T; scanf("%d", &T);
while(T --)
{
scanf("%lf", &k);
solve();
}
return 0;
}
I-New Teaching
Buildings
佔坑
這題太噁心了,暴力開的話記憶體根本開不下。所以需要求的時候實時求一點。比賽的時候感覺複雜度可能不太行。就沒仔細調。。
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 50010;
#include<bitset>
bitset<maxn> dp[5][510], tmp, tmp2;
int n, m, q;
int a[5][maxn];
int id[5][maxn], t, sz[5][maxn];
bool cmp(int i, int j)
{
return a[t][i] < a[t][j];
}
inline int get_int(){
int ret=0;char c;
while(!isdigit(c=getchar()));
do {ret = (ret<<3)+(ret<<1)+c-'0';
}while(isdigit(c=getchar()));
return ret;
}
void solve()
{
CLR(sz, 0);
for(int i = 0; i < 5; i ++)
{
t = i;
for(int j = 1; j <= n; j ++)
id[i][j] = j, sz[i][a[i][j]] ++;
sort(id[i] + 1, id[i] + n + 1, cmp);
for(int j = 1; j <= m; j ++)
sz[i][j] += sz[i][j - 1];
for(int j = 0; j <= 501; j ++) dp[i][j].reset();
for(int j = 1; j <= n; j ++)
{
if(j % 100 == 0)
{
dp[i][j / 100] = dp[i][j / 100 - 1];
for(int k = j - 99; k <= j; k ++)
dp[i][j / 100][id[i][k]] = 1;
}
}
}
scanf("%d", &q);
int ans = 0;
while(q --)
{
int ask[6];
for(int j = 0; j < 5; j ++)
{
ask[j] = get_int();
ask[j] ^= ans;
}
tmp = dp[0][sz[0][ask[0]] / 100];
for(int i = sz[0][ask[0]] / 100 * 100 + 1; i <= sz[0][ask[0]]; i ++)
tmp[id[0][i]] = 1;
for(int j = 1; j < 5; j ++)
{
tmp2 = dp[j][sz[j][ask[j]] / 100];
for(int i = sz[j][ask[j]] / 100 *100 + 1; i <= sz[j][ask[j]]; i ++)
tmp2[id[j][i]] = 1;
tmp &= tmp2;
}
printf("%d\n", ans = tmp.count());
}
}
int main()
{
int T; scanf("%d", &T);
while(T --)
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)
{
for(int j = 0; j < 5; j ++)
a[j][i] = get_int();
}
solve();
}
return 0;
}