D:從後往前考慮每一個人,顯然若是能移到最後一我的後方就應該當即移動,不然移不移沒什麼影響。鏈表暴力模擬這個過程便可。容易發現複雜度是線性的(判斷兩人間是否有邊可能須要帶log)。固然事實上根本不須要鏈表,直接檢查其對後方未刪除點的出度之和便可。ios
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<map> using namespace std; #define ll long long #define N 300010 #define M 500010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,a[N],p[N],t,nxt[N],pre[N],degree[N],ans; map<int,int> f[N]; void del(int k) { nxt[pre[k]]=nxt[k]; pre[nxt[k]]=pre[k]; } signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<=m;i++) { int x=read(),y=read(); f[x][y]=1;degree[x]++; } for (int i=0;i<n;i++) nxt[i]=i+1; for (int i=1;i<=n;i++) pre[i]=i-1; for (int i=n-1;i>=1;i--) { int x=a[i]; if (f[x][a[n]]) { if (n-i-ans>degree[x]) continue; int u=i; while (u!=n) { if (!f[x][a[nxt[u]]]) break; u=nxt[u]; } if (u==n) { ans++; del(i); } } } cout<<ans; return 0; //NOTICE LONG LONG!!!!! }
E:分塊,每塊維護第一個數和塊的總和。注意到每次修改影響的是一段連續區間,因而根據塊的第一個數暴力找到最後一個影響塊,對其以前的塊更新第一個數與總和,修改點所在的塊和最後一個塊暴力重構。查詢時暴力重構端點所在的塊就完了。固然也能夠線段樹,作法相似。spa
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<map> using namespace std; #define ll long long #define N 100010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,q,b[N],block,num,pos[N],L[N],R[N]; ll S[N],SS[N],sum[N],a[N],first[N],val[N]; void update(int k) { a[L[k]]=first[k];sum[k]=a[L[k]]; for (int i=L[k]+1;i<=R[k];i++) a[i]=max(a[i],a[i-1]+b[i-1]),sum[k]+=a[i]; } signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read();block=sqrt(n);num=(n-1)/block+1; for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<n;i++) b[i]=read(); for (int i=1;i<n;i++) S[i]=S[i-1]+b[i]; for (int i=1;i<=num;i++) { L[i]=R[i-1]+1;R[i]=min(n,L[i]+block-1); for (int j=L[i];j<=R[i];j++) { if (j==L[i]) SS[j]=0; else SS[j]=SS[j-1]+b[j-1]; val[i]+=SS[j]; pos[j]=i,sum[i]+=a[j]; } first[i]=a[L[i]]; } q=read(); while (q--) { char c=getchar(); while (c!='+'&&c!='s') c=getchar(); if (c=='+') { int p=read(),x=read(); update(pos[p]); a[p]+=x;if (p==L[pos[p]]) first[pos[p]]+=x; update(pos[p]); int u=num+1; for (int i=pos[p]+1;i<=num;i++) if (first[i]>a[p]+S[L[i]-1]-S[p-1]) {u=i;break;} u--; for (int i=pos[p]+1;i<u;i++) first[i]=a[p]+S[L[i]-1]-S[p-1], sum[i]=1ll*first[i]*(R[i]-L[i]+1)+val[i]; if (u!=pos[p]) { first[u]=a[p]+S[L[u]-1]-S[p-1]; update(u); } } else { int l=read(),r=read(); if (pos[l]==pos[r]) { update(pos[l]);ll ans=0; for (int i=l;i<=r;i++) ans+=a[i]; printf("%I64d\n",ans); } else { update(pos[l]),update(pos[r]);ll ans=0; for (int i=l;i<=R[pos[l]];i++) ans+=a[i]; for (int i=L[pos[r]];i<=r;i++) ans+=a[i]; for (int i=pos[l]+1;i<pos[r];i++) ans+=sum[i]; printf("%I64d\n",ans); } } } return 0; //NOTICE LONG LONG!!!!! }