小$P$的咕事
总结:
还行,就是$T1$写的慢了,$T2,T3$暴力有点锅
T1
小模拟。
打就是了。
可以小小的手玩一下。
(考试的时候某同志人肉对拍了$20min$)=.=
418 ms | 360 KiB | C++11 / 4.1 K |
#include <iostream> #include <cstring> #include <cstdio> #include <vector> #define N 10 #define Up 0 #define Down 1 #define Left 2 #define Right 3 #define LL long long using namespace std; int bd[N][N],legal=0; int bef[N][N],aft[N][N]; int bl,chn; bool failed=0; LL sco=0; vector<int> dat; void pour(){ for(int i=1;i<=bl;i++){ for(int j=1;j<=bl;j++){ if(bd[i][j]==0)printf(" "); else printf("%4d",bd[i][j]); }puts(""); } } void tou(){ int num; for(int c=1;c<=bl;c++){ num=0; dat.clear(); for(int l=1;l<=bl;l++){ // cout<<l<<" "<<c<<" "<<num<<endl; // for(int i:dat){ // cout<<i<<" "; // } // if(!dat.empty())cout<<endl; if(bd[l][c]==0)continue; if(num==0)num=bd[l][c]; else { if(num==bd[l][c]){ dat.push_back(num<<1); sco+=num<<1; num=0; } else{ dat.push_back(num); num=bd[l][c]; } } } if(num!=0)dat.push_back(num); int vid=0; for(int l=1;l<=bl;l++) bd[l][c]=0; for(int l=1;l<=bl;l++){ if(vid==dat.size()) break;//All set bd[l][c]=dat[vid]; vid++; } } } void tod(){ int num; for(int c=1;c<=bl;c++){ num=0; dat.clear(); for(int l=bl;l>=1;l--){ // cout<<l<<" "<<c<<" "<<num<<endl; if(bd[l][c]==0)continue; if(num==0)num=bd[l][c]; else { if(num==bd[l][c]){ dat.push_back(num<<1); sco+=num<<1; num=0; } else{ dat.push_back(num); num=bd[l][c]; } } } if(num!=0)dat.push_back(num); int vid=0; for(int l=bl;l>=1;l--) bd[l][c]=0; for(int l=bl;l>=1;l--){ if(vid==dat.size()) break;//All set bd[l][c]=dat[vid]; vid++; } } } void tol(){ int num; for(int l=1;l<=bl;l++){ num=0; dat.clear(); for(int c=1;c<=bl;c++){ if(bd[l][c]==0)continue; if(num==0)num=bd[l][c]; else { if(num==bd[l][c]){ dat.push_back(num<<1); sco+=num<<1; num=0; } else{ dat.push_back(num); num=bd[l][c]; } } } if(num!=0)dat.push_back(num); int vid=0; for(int c=1;c<=bl;c++) bd[l][c]=0; for(int c=1;c<=bl;c++){ if(vid==dat.size()) break;//All set bd[l][c]=dat[vid]; vid++; } } } void tor(){ int num; for(int l=1;l<=bl;l++){ num=0; dat.clear(); for(int c=bl;c>=1;c--){ if(bd[l][c]==0)continue; if(num==0)num=bd[l][c]; else { if(num==bd[l][c]){ dat.push_back(num<<1); sco+=num<<1; num=0; } else{ dat.push_back(num); num=bd[l][c]; } } } if(num!=0)dat.push_back(num); int vid=0; for(int c=bl;c>=1;c--) bd[l][c]=0; for(int c=bl;c>=1;c--){ if(vid==dat.size()) break;//All set bd[l][c]=dat[vid]; vid++; } } } void make_new(int k,int val){ int tot=0,cnt=0; for(int i=1;i<=bl;i++) for(int j=1;j<=bl;j++) if(bd[i][j]==0)tot++; if(tot==0)return ; k=1+k%tot; for(int i=1;i<=bl;i++){ for(int j=1;j<=bl;j++){ if(bd[i][j]==0){ cnt++; if(cnt==k){ bd[i][j]=val; return ; } } } } } bool check(){ for(int i=1;i<=bl;i++) for(int j=1;j<=bl;j++) if(aft[i][j]!=bef[i][j])return 1; return 0; } int main(){ int a,b,c; // freopen("game.in" ,"r",stdin); // freopen("game.out","w",stdout); scanf("%d%d",&bl,&chn); scanf("%d%d%d",&a,&b,&c); bd[a][b]=c; scanf("%d%d%d",&a,&b,&c); bd[a][b]=c; for(int i=1;i<=chn;i++){ scanf("%d%d%d",&a,&b,&c); for(int j=1;j<=bl;j++) for(int k=1;k<=bl;k++) bef[j][k]=bd[j][k]; // puts("============================"); // pour(); switch(a){ case Up:// cout<<"---------Up------------"<<endl; tou(); break; case Down:// cout<<"--------Down------"<<endl; tod(); break; case Left://cout<<"----------Left--------"<<endl; tol(); break; case Right: //cout<<"----------Right-----------"<<endl; tor(); break; default:puts("Wrong Input"); } // pour(); for(int j=1;j<=bl;j++) for(int k=1;k<=bl;k++) aft[j][k]=bd[j][k]; if(!check())break; legal++; make_new(b,c); } printf("%d %lld ",legal,sco); }
T2
终于让我用树状数组维护了一回$dp$
树状数组太棒辣!
××话说我刚开始颓了半天如何维护区间最值。(话说我只要前后缀……)
不过我都打了点了不如放在这……
#define N 111111 int pre[N]; inline int lowbit(int x){return x&(-x);} void chan(int pos,int val){//修值 while(pos<=pn){ pre[pos]=val; int ppos=lowbit(pos); for(int i=1;i<ppos;i<<=1) ch[x]=max(ch[x],ch[x-i]); pos+=lowbit(pos); } } int maxn(int l,int r){//查值 int res=0; while(l<=r){ res=max(pre[r],res); r--; for(;r-lowbit(r)>=l;r-=lowbit(r)) res=max(pre[r],res); } return res; }
然后才是正解$qwq$
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #define N 111111 #define LF double using namespace std; int nn,vn,arr[N],val[N]; LF pre[N],aft[N]; LF szsz[N],ans; inline int fvind(int v){return lower_bound(val+1,val+vn+1,v)-val;} inline int lowbit(int x){return x&(-x);} void add(int pos,LF va){ while(pos<=nn){ szsz[pos]=max(szsz[pos],va); pos+=lowbit(pos); } } LF query(int pos){ LF res=0; while(pos){ res=max(res,szsz[pos]); pos-=lowbit(pos); } return res; } int main(){ scanf("%d",&nn); for(int i=1;i<=nn;i++){ scanf("%d",arr+i); val[i]=arr[i]; } sort(val+1,val+nn+1); vn=unique(val+1,val+nn+1)-val-1; for(int i=1;i<=nn;i++) arr[i]=fvind(arr[i]); for(int i=1;i<=nn;i++){ pre[i]=query(arr[i]-1)+val[arr[i]]; add(arr[i],pre[i]); } memset(szsz,0,sizeof szsz); for(int i=nn;i>=1;i--){ aft[i]=query(arr[i]-1)+val[arr[i]]; add(arr[i],aft[i]); } for(int i=1;i<=nn;i++){ // cout<<pre[i]<<" "<<aft[i]<<endl; ans=max(ans,pre[i]); // ans=max(ans,aft[i]); ans=max(ans,(pre[i]+aft[i]-val[arr[i]])/2.0); } printf("%.3lf ",ans); }
T3
打法一:
随机化
打法二:
随机化
打法三:
随机化
打法四:
随机化
打法五:
枚举斜率直接把每个复数看成向量投影在斜率方向,最后搞一搞。$(gugugu)$